From f73269708f365abd7bd4412416b8b52a098c3dfb Mon Sep 17 00:00:00 2001 From: Paul Hebble Date: Fri, 12 Apr 2024 09:51:02 -0500 Subject: [PATCH 1/4] Get "CKAN" From Meta.GetProductName --- ConsoleUI/AuthTokenListScreen.cs | 2 +- ConsoleUI/DeleteDirectoriesScreen.cs | 2 +- ConsoleUI/DependencyScreen.cs | 5 +---- ConsoleUI/ExitScreen.cs | 2 +- ConsoleUI/GameInstanceListScreen.cs | 2 +- ConsoleUI/GameInstanceScreen.cs | 2 +- ConsoleUI/InstallFiltersScreen.cs | 2 +- ConsoleUI/ModInfoScreen.cs | 2 +- ConsoleUI/ModListScreen.cs | 2 +- ConsoleUI/ProgressScreen.cs | 2 +- ConsoleUI/RepoScreen.cs | 2 +- 11 files changed, 11 insertions(+), 14 deletions(-) diff --git a/ConsoleUI/AuthTokenListScreen.cs b/ConsoleUI/AuthTokenListScreen.cs index c082215909..e7d20803ed 100644 --- a/ConsoleUI/AuthTokenListScreen.cs +++ b/ConsoleUI/AuthTokenListScreen.cs @@ -85,7 +85,7 @@ public AuthTokenScreen() : base() /// protected override string LeftHeader() { - return $"CKAN {Meta.GetVersion()}"; + return $"{Meta.GetProductName()} {Meta.GetVersion()}"; } /// diff --git a/ConsoleUI/DeleteDirectoriesScreen.cs b/ConsoleUI/DeleteDirectoriesScreen.cs index 75e163bd0b..057291b147 100644 --- a/ConsoleUI/DeleteDirectoriesScreen.cs +++ b/ConsoleUI/DeleteDirectoriesScreen.cs @@ -107,7 +107,7 @@ private void PopulateFiles() /// /// Put CKAN 1.25.5 in top left corner /// - protected override string LeftHeader() => $"CKAN {Meta.GetVersion()}"; + protected override string LeftHeader() => $"{Meta.GetProductName()} {Meta.GetVersion()}"; /// /// Show the Delete Directories header diff --git a/ConsoleUI/DependencyScreen.cs b/ConsoleUI/DependencyScreen.cs index 1e61beb7e7..f989827760 100644 --- a/ConsoleUI/DependencyScreen.cs +++ b/ConsoleUI/DependencyScreen.cs @@ -126,10 +126,7 @@ public DependencyScreen(GameInstanceManager mgr, Registry registry, ChangePlan c /// /// Put CKAN 1.25.5 in top left corner /// - protected override string LeftHeader() - { - return $"CKAN {Meta.GetVersion()}"; - } + protected override string LeftHeader() => $"{Meta.GetProductName()} {Meta.GetVersion()}"; /// /// Put description in top center diff --git a/ConsoleUI/ExitScreen.cs b/ConsoleUI/ExitScreen.cs index ad74be0125..7a2b7dc5b5 100644 --- a/ConsoleUI/ExitScreen.cs +++ b/ConsoleUI/ExitScreen.cs @@ -49,7 +49,7 @@ private void Draw(ConsoleTheme theme) // Specially formatted snippets var ckanPiece = new FancyLinePiece(Meta.GetProductName(), theme.ExitInnerBg, theme.ExitHighlightFg); - var ckanVersionPiece = new FancyLinePiece($"CKAN {Meta.GetVersion()}", theme.ExitInnerBg, theme.ExitHighlightFg); + var ckanVersionPiece = new FancyLinePiece($"{Meta.GetProductName()} {Meta.GetVersion()}", theme.ExitInnerBg, theme.ExitHighlightFg); var releaseLinkPiece = new FancyLinePiece("https://github.com/KSP-CKAN/CKAN/releases/latest", theme.ExitInnerBg, theme.ExitLinkFg); var issuesLinkPiece = new FancyLinePiece("https://github.com/KSP-CKAN/CKAN/issues", theme.ExitInnerBg, theme.ExitLinkFg); var authorsLinkPiece = new FancyLinePiece("https://github.com/KSP-CKAN/CKAN/graphs/contributors", theme.ExitInnerBg, theme.ExitLinkFg); diff --git a/ConsoleUI/GameInstanceListScreen.cs b/ConsoleUI/GameInstanceListScreen.cs index 9a5973f73a..685c9acd10 100644 --- a/ConsoleUI/GameInstanceListScreen.cs +++ b/ConsoleUI/GameInstanceListScreen.cs @@ -149,7 +149,7 @@ public GameInstanceListScreen(GameInstanceManager mgr, RepositoryDataManager rep /// protected override string LeftHeader() { - return $"CKAN {Meta.GetVersion()}"; + return $"{Meta.GetProductName()} {Meta.GetVersion()}"; } /// diff --git a/ConsoleUI/GameInstanceScreen.cs b/ConsoleUI/GameInstanceScreen.cs index 060368527a..4122ef4152 100644 --- a/ConsoleUI/GameInstanceScreen.cs +++ b/ConsoleUI/GameInstanceScreen.cs @@ -55,7 +55,7 @@ protected GameInstanceScreen(GameInstanceManager mgr, string initName = "", stri /// protected override string LeftHeader() { - return $"CKAN {Meta.GetVersion()}"; + return $"{Meta.GetProductName()} {Meta.GetVersion()}"; } /// diff --git a/ConsoleUI/InstallFiltersScreen.cs b/ConsoleUI/InstallFiltersScreen.cs index d212102c2b..0cf018885e 100644 --- a/ConsoleUI/InstallFiltersScreen.cs +++ b/ConsoleUI/InstallFiltersScreen.cs @@ -97,7 +97,7 @@ public InstallFiltersScreen(IConfiguration globalConfig, GameInstance instance) /// protected override string LeftHeader() { - return $"CKAN {Meta.GetVersion()}"; + return $"{Meta.GetProductName()} {Meta.GetVersion()}"; } /// diff --git a/ConsoleUI/ModInfoScreen.cs b/ConsoleUI/ModInfoScreen.cs index aa14ec1bb3..b81707930c 100644 --- a/ConsoleUI/ModInfoScreen.cs +++ b/ConsoleUI/ModInfoScreen.cs @@ -198,7 +198,7 @@ public ModInfoScreen(GameInstanceManager mgr, Registry registry, ChangePlan cp, /// protected override string LeftHeader() { - return $"CKAN {Meta.GetVersion()}"; + return $"{Meta.GetProductName()} {Meta.GetVersion()}"; } /// diff --git a/ConsoleUI/ModListScreen.cs b/ConsoleUI/ModListScreen.cs index 72b89aafa5..7fc0a8dc79 100644 --- a/ConsoleUI/ModListScreen.cs +++ b/ConsoleUI/ModListScreen.cs @@ -351,7 +351,7 @@ public ModListScreen(GameInstanceManager mgr, RepositoryDataManager repoData, Re /// protected override string LeftHeader() { - return $"CKAN {Meta.GetVersion()}"; + return $"{Meta.GetProductName()} {Meta.GetVersion()}"; } /// diff --git a/ConsoleUI/ProgressScreen.cs b/ConsoleUI/ProgressScreen.cs index 2e787c962b..b4bf38b69a 100644 --- a/ConsoleUI/ProgressScreen.cs +++ b/ConsoleUI/ProgressScreen.cs @@ -47,7 +47,7 @@ public ProgressScreen(string descrip, string initMsg = "") /// protected override string LeftHeader() { - return $"CKAN {Meta.GetVersion()}"; + return $"{Meta.GetProductName()} {Meta.GetVersion()}"; } /// diff --git a/ConsoleUI/RepoScreen.cs b/ConsoleUI/RepoScreen.cs index 5fb671cae6..d3c02b4f96 100644 --- a/ConsoleUI/RepoScreen.cs +++ b/ConsoleUI/RepoScreen.cs @@ -75,7 +75,7 @@ protected RepoScreen(IGame game, SortedDictionary reps, stri /// protected override string LeftHeader() { - return $"CKAN {Meta.GetVersion()}"; + return $"{Meta.GetProductName()} {Meta.GetVersion()}"; } /// From 05d84be07c2e3ef2f2984e4a525455dba0f2228c Mon Sep 17 00:00:00 2001 From: Paul Hebble Date: Wed, 8 May 2024 13:39:36 -0500 Subject: [PATCH 2/4] Platform specific format for export path --- ConsoleUI/ModListScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ConsoleUI/ModListScreen.cs b/ConsoleUI/ModListScreen.cs index 7fc0a8dc79..6963bf4c9d 100644 --- a/ConsoleUI/ModListScreen.cs +++ b/ConsoleUI/ModListScreen.cs @@ -619,7 +619,7 @@ private bool ExportInstalled(ConsoleTheme theme) // Because that's supposed to work. regMgr.Save(true); string path = Path.Combine( - manager.CurrentInstance.CkanDir(), + Platform.FormatPath(manager.CurrentInstance.CkanDir()), $"{Properties.Resources.ModListExportPrefix}-{manager.CurrentInstance.Name}.ckan" ); RaiseError(Properties.Resources.ModListExported, path); From 9fb7436f1c9e8a39e788e02038ffbf0c8dde49fb Mon Sep 17 00:00:00 2001 From: Paul Hebble Date: Fri, 12 Apr 2024 10:00:27 -0500 Subject: [PATCH 3/4] Trivial coding style changes --- ConsoleUI/DependencyScreen.cs | 141 +++++++++++----------------- Core/Repositories/RepositoryData.cs | 2 +- 2 files changed, 58 insertions(+), 85 deletions(-) diff --git a/ConsoleUI/DependencyScreen.cs b/ConsoleUI/DependencyScreen.cs index f989827760..21f6b404d3 100644 --- a/ConsoleUI/DependencyScreen.cs +++ b/ConsoleUI/DependencyScreen.cs @@ -2,6 +2,11 @@ using System.Linq; using System.ComponentModel; using System.Collections.Generic; + +using CKAN.Versioning; +#if NETFRAMEWORK +using CKAN.Extensions; +#endif using CKAN.ConsoleUI.Toolkit; namespace CKAN.ConsoleUI { @@ -16,31 +21,26 @@ public class DependencyScreen : ConsoleScreen { /// Initialize the screen /// /// Game instance manager containing instances - /// Registry of the current instance for finding mods + /// Registry of the current instance for finding mods /// Plan of mods to add and remove /// Mods that the user saw and did not select, in this pass or a previous pass /// True if debug options should be available, false otherwise - public DependencyScreen(GameInstanceManager mgr, Registry registry, ChangePlan cp, HashSet rej, bool dbg) : base() + public DependencyScreen(GameInstanceManager mgr, Registry reg, ChangePlan cp, HashSet rej, bool dbg) : base() { - debug = dbg; - manager = mgr; - plan = cp; - this.registry = registry; - installer = new ModuleInstaller(manager.CurrentInstance, manager.Cache, this); - rejected = rej; - - AddObject(new ConsoleLabel( - 1, 2, -1, - () => Properties.Resources.RecommendationsLabel - )); - - HashSet sourceModules = new HashSet(); - sourceModules.UnionWith(plan.Install); - sourceModules.UnionWith(new HashSet( - ReplacementIdentifiers(plan.Replace) - .Select(id => registry.InstalledModule(id).Module) - )); - generateList(sourceModules); + debug = dbg; + manager = mgr; + plan = cp; + registry = reg; + rejected = rej; + + AddObject(new ConsoleLabel(1, 2, -1, + () => Properties.Resources.RecommendationsLabel)); + + generateList(new ModuleInstaller(manager.CurrentInstance, manager.Cache, this), + plan.Install + .Concat(ReplacementModules(plan.Replace, + manager.CurrentInstance.VersionCriteria())) + .ToHashSet()); dependencyList = new ConsoleListBox( 1, 4, -1, -2, @@ -49,17 +49,17 @@ public DependencyScreen(GameInstanceManager mgr, Registry registry, ChangePlan c new ConsoleListBoxColumn() { Header = Properties.Resources.RecommendationsInstallHeader, Width = 7, - Renderer = (Dependency d) => StatusSymbol(d.module) + Renderer = (Dependency d) => StatusSymbol(d.module), }, new ConsoleListBoxColumn() { Header = Properties.Resources.RecommendationsNameHeader, Width = null, - Renderer = (Dependency d) => d.module.ToString() + Renderer = (Dependency d) => d.module.ToString(), }, new ConsoleListBoxColumn() { Header = Properties.Resources.RecommendationsSourcesHeader, Width = 42, - Renderer = (Dependency d) => string.Join(", ", d.dependents) + Renderer = (Dependency d) => string.Join(", ", d.dependents), } }, 1, 0, ListSortDirection.Descending @@ -89,10 +89,9 @@ public DependencyScreen(GameInstanceManager mgr, Registry registry, ChangePlan c dependencyList.AddTip(Properties.Resources.Enter, Properties.Resources.Details); dependencyList.AddBinding(Keys.Enter, (object sender, ConsoleTheme theme) => { if (dependencyList.Selection != null) { - LaunchSubScreen(theme, new ModInfoScreen( - manager, registry, plan, - dependencyList.Selection.module, - debug)); + LaunchSubScreen(theme, new ModInfoScreen(manager, reg, plan, + dependencyList.Selection.module, + debug)); } return true; }); @@ -102,9 +101,7 @@ public DependencyScreen(GameInstanceManager mgr, Registry registry, ChangePlan c AddTip(Properties.Resources.Esc, Properties.Resources.Cancel); AddBinding(Keys.Escape, (object sender, ConsoleTheme theme) => { // Add everything to rejected - foreach (var kvp in dependencies) { - rejected.Add(kvp.Key.identifier); - } + rejected.UnionWith(dependencies.Keys.Select(m => m.identifier)); return false; }); @@ -131,21 +128,15 @@ public DependencyScreen(GameInstanceManager mgr, Registry registry, ChangePlan c /// /// Put description in top center /// - protected override string CenterHeader() - { - return Properties.Resources.RecommendationsTitle; - } + protected override string CenterHeader() => Properties.Resources.RecommendationsTitle; /// /// Return whether there are any options to show. /// ModListScreen uses this to avoid showing this screen when empty. /// - public bool HaveOptions() - { - return dependencies.Count > 0; - } + public bool HaveOptions() => dependencies.Count > 0; - private void generateList(HashSet inst) + private void generateList(ModuleInstaller installer, HashSet inst) { if (installer.FindRecommendations( inst, new List(inst), registry as Registry, @@ -153,66 +144,53 @@ private void generateList(HashSet inst) out Dictionary> suggestions, out Dictionary> supporters )) { - foreach (var kvp in recommendations) { - dependencies.Add(kvp.Key, new Dependency() { - module = kvp.Key, - defaultInstall = kvp.Value.Item1, - dependents = kvp.Value.Item2.OrderBy(d => d).ToList() + foreach ((CkanModule mod, Tuple> checkedAndDependents) in recommendations) { + dependencies.Add(mod, new Dependency() { + module = mod, + dependents = checkedAndDependents.Item2.OrderBy(d => d).ToList() }); - if (kvp.Value.Item1) { - accepted.Add(kvp.Key); - } } - foreach (var kvp in suggestions) { - dependencies.Add(kvp.Key, new Dependency() { - module = kvp.Key, - defaultInstall = false, - dependents = kvp.Value.OrderBy(d => d).ToList() + foreach ((CkanModule mod, List dependents) in suggestions) { + dependencies.Add(mod, new Dependency() { + module = mod, + dependents = dependents.OrderBy(d => d).ToList() }); } - foreach (var kvp in supporters) { - dependencies.Add(kvp.Key, new Dependency() { - module = kvp.Key, - defaultInstall = false, - dependents = kvp.Value.OrderBy(d => d).ToList() + foreach ((CkanModule mod, HashSet dependents) in supporters) { + dependencies.Add(mod, new Dependency() { + module = mod, + dependents = dependents.OrderBy(d => d).ToList() }); } + // Check the default checkboxes + accepted.UnionWith(recommendations.Where(kvp => kvp.Value.Item1) + .Select(kvp => kvp.Key)); } } - private IEnumerable ReplacementIdentifiers(IEnumerable replaced_identifiers) - { - foreach (string replaced in replaced_identifiers) { - ModuleReplacement repl = registry.GetReplacement( - replaced, manager.CurrentInstance.VersionCriteria() - ); - if (repl != null) { - yield return repl.ReplaceWith.identifier; - } - } - } + private IEnumerable ReplacementModules(IEnumerable replaced_identifiers, + GameVersionCriteria crit) + => replaced_identifiers.Select(replaced => registry.GetReplacement(replaced, crit)) + .Where(repl => repl != null) + .Select(repl => repl.ReplaceWith); private string StatusSymbol(CkanModule mod) - { - return accepted.Contains(mod) - ? installing - : notinstalled; - } + => accepted.Contains(mod) ? installing + : notinstalled; private readonly HashSet accepted = new HashSet(); private readonly HashSet rejected; private readonly IRegistryQuerier registry; private readonly GameInstanceManager manager; - private readonly ModuleInstaller installer; private readonly ChangePlan plan; private readonly bool debug; private readonly Dictionary dependencies = new Dictionary(); private readonly ConsoleListBox dependencyList; - private static readonly string notinstalled = " "; - private static readonly string installing = "+"; + private const string notinstalled = " "; + private const string installing = "+"; } /// @@ -221,14 +199,9 @@ private string StatusSymbol(CkanModule mod) public class Dependency { /// - /// Identifier of mod - /// - public CkanModule module; - - /// - /// True if we default to installing, false otherwise + /// The mod /// - public bool defaultInstall; + public CkanModule module; /// /// List of mods that recommended or suggested this mod diff --git a/Core/Repositories/RepositoryData.cs b/Core/Repositories/RepositoryData.cs index e6ef66240a..3b4e11ef75 100644 --- a/Core/Repositories/RepositoryData.cs +++ b/Core/Repositories/RepositoryData.cs @@ -372,7 +372,7 @@ private static CkanModule ProcessRegistryMetadataFromJSON(string metadata, strin } // If we haven't handled our exception, then it really was exceptional. - if (handled == false) + if (!handled) { if (exception == null) { From 8d50fd7932e2c7fd6247d0b5b8a2a0abda817df7 Mon Sep 17 00:00:00 2001 From: Paul Hebble Date: Fri, 12 Apr 2024 11:13:28 -0500 Subject: [PATCH 4/4] Conflicting recommendations check for ConsoleUI --- ConsoleUI/DependencyScreen.cs | 60 +++++++++++++++++++++++++++-------- ConsoleUI/InstallScreen.cs | 3 +- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/ConsoleUI/DependencyScreen.cs b/ConsoleUI/DependencyScreen.cs index 21f6b404d3..b20b53d364 100644 --- a/ConsoleUI/DependencyScreen.cs +++ b/ConsoleUI/DependencyScreen.cs @@ -66,15 +66,20 @@ public DependencyScreen(GameInstanceManager mgr, Registry reg, ChangePlan cp, Ha ); dependencyList.AddTip("+", Properties.Resources.Toggle); dependencyList.AddBinding(Keys.Plus, (object sender, ConsoleTheme theme) => { - ChangePlan.toggleContains(accepted, dependencyList.Selection.module); + var mod = dependencyList.Selection.module; + if (accepted.Contains(mod) || TryWithoutConflicts(accepted.Append(mod))) { + ChangePlan.toggleContains(accepted, mod); + } return true; }); dependencyList.AddTip($"{Properties.Resources.Ctrl}+A", Properties.Resources.SelectAll); dependencyList.AddBinding(Keys.CtrlA, (object sender, ConsoleTheme theme) => { - foreach (var kvp in dependencies) { - if (!accepted.Contains(kvp.Key)) { - ChangePlan.toggleContains(accepted, kvp.Key); + if (TryWithoutConflicts(dependencies.Keys)) { + foreach (var kvp in dependencies) { + if (!accepted.Contains(kvp.Key)) { + ChangePlan.toggleContains(accepted, kvp.Key); + } } } return true; @@ -107,16 +112,15 @@ public DependencyScreen(GameInstanceManager mgr, Registry reg, ChangePlan cp, Ha AddTip("F9", Properties.Resources.Accept); AddBinding(Keys.F9, (object sender, ConsoleTheme theme) => { - foreach (CkanModule mod in accepted) { - plan.Install.Add(mod); - } - // Add the rest to rejected - foreach (var kvp in dependencies) { - if (!accepted.Contains(kvp.Key)) { - rejected.Add(kvp.Key.identifier); - } + if (TryWithoutConflicts(accepted)) { + plan.Install.UnionWith(accepted); + // Add the rest to rejected + rejected.UnionWith(dependencies.Keys + .Except(accepted) + .Select(m => m.identifier)); + return false; } - return false; + return true; }); } @@ -178,6 +182,36 @@ private string StatusSymbol(CkanModule mod) => accepted.Contains(mod) ? installing : notinstalled; + private bool TryWithoutConflicts(IEnumerable toAdd) + { + if (HasConflicts(toAdd, out List conflictDescriptions)) { + RaiseError("{0}", string.Join(Environment.NewLine, + conflictDescriptions)); + return false; + } + return true; + } + + private bool HasConflicts(IEnumerable toAdd, + out List descriptions) + { + try + { + var resolver = new RelationshipResolver( + plan.Install.Concat(toAdd).Distinct(), + plan.Remove.Select(ident => registry.InstalledModule(ident)?.Module), + RelationshipResolverOptions.ConflictsOpts(), registry, + manager.CurrentInstance.VersionCriteria()); + descriptions = resolver.ConflictDescriptions.ToList(); + return descriptions.Count > 0; + } + catch (DependencyNotSatisfiedKraken k) + { + descriptions = new List() { k.Message }; + return true; + } + } + private readonly HashSet accepted = new HashSet(); private readonly HashSet rejected; diff --git a/ConsoleUI/InstallScreen.cs b/ConsoleUI/InstallScreen.cs index 46c6e99879..969c49c830 100644 --- a/ConsoleUI/InstallScreen.cs +++ b/ConsoleUI/InstallScreen.cs @@ -81,7 +81,8 @@ public override void Run(ConsoleTheme theme, Action process = null registry.InstalledModules .Select(im => im.Module) .ToArray(), - plan.Install)) + plan.Install) + ?? m) .ToArray(); inst.InstallList(iList, resolvOpts, regMgr, ref possibleConfigOnlyDirs, dl); plan.Install.Clear();