From f6afe59eafb49866930c0479cab031af2efe897f Mon Sep 17 00:00:00 2001 From: Paul Hebble Date: Tue, 14 May 2019 19:33:51 +0000 Subject: [PATCH] Update GUI modlist if scan detects changes --- Core/KSP.cs | 35 ++++++++++++++------------ Core/Registry/RegistryManager.cs | 42 +++++++++++++++++++++++++++++--- GUI/MainRepo.cs | 9 +++++-- 3 files changed, 66 insertions(+), 20 deletions(-) diff --git a/Core/KSP.cs b/Core/KSP.cs index b10eedb2ea..14e3797096 100644 --- a/Core/KSP.cs +++ b/Core/KSP.cs @@ -404,13 +404,17 @@ public KspVersionCriteria VersionCriteria() /// Clears the registry of DLL data, and refreshes it by scanning GameData. /// This operates as a transaction. /// This *saves* the registry upon completion. + /// TODO: This would likely be better in the Registry class itself. /// - // TODO: This would likely be better in the Registry class itself. - public void ScanGameData() + /// + /// True if found anything different, false if same as before + /// + public bool ScanGameData() { var manager = RegistryManager.Instance(this); using (TransactionScope tx = CkanTransaction.CreateTransactionScope()) { + var oldDlls = new HashSet(manager.registry.InstalledDlls); manager.registry.ClearDlls(); // TODO: It would be great to optimise this to skip .git directories and the like. @@ -421,27 +425,28 @@ public void ScanGameData() // GameData *twice*. // // The least evil is to walk it once, and filter it ourselves. - IEnumerable files = Directory.EnumerateFiles( - GameData(), - "*", - SearchOption.AllDirectories - ); + IEnumerable files = Directory + .EnumerateFiles(GameData(), "*", SearchOption.AllDirectories) + .Where(file => dllRegex.IsMatch(file)) + .Select(KSPPathUtils.NormalizePath) + .Where(absPath => !DllIgnoreList.Contains(ToRelativeGameDir(absPath))); - files = files.Where(file => Regex.IsMatch(file, @"\.dll$", RegexOptions.IgnoreCase)); - - foreach (string dll in files.Select(KSPPathUtils.NormalizePath)) + foreach (string dll in files) { - var relativePath = ToRelativeGameDir(dll); - - if (!DllIgnoreList.Contains(relativePath)) - manager.registry.RegisterDll(this, dll); + manager.registry.RegisterDll(this, dll); } + var newDlls = new HashSet(manager.registry.InstalledDlls); + bool dllChanged = !oldDlls.SetEquals(newDlls); - manager.ScanDlc(); + bool dlcChanged = manager.ScanDlc(); manager.Save(false); tx.Complete(); + + return dllChanged || dlcChanged; } } + + private static readonly Regex dllRegex = new Regex(@"\.dll$", RegexOptions.IgnoreCase | RegexOptions.Compiled); #endregion diff --git a/Core/Registry/RegistryManager.cs b/Core/Registry/RegistryManager.cs index 32ddf6bbec..88ed7c26e5 100644 --- a/Core/Registry/RegistryManager.cs +++ b/Core/Registry/RegistryManager.cs @@ -469,22 +469,58 @@ public void ExportInstalled(string path, bool recommends, bool with_versions) file_transaction.WriteAllText(path, serialized); } - public void ScanDlc() + /// + /// Look for DLC installed in GameData + /// + /// + /// True if not the same list as last scan, false otherwise + /// + public bool ScanDlc() { - var testDlc = TestDlcScan(); - var wellKnownDlc = WellKnownDlcScan(); + var dlc = new Dictionary(registry.InstalledDlc); + UnmanagedModuleVersion foundVer; + bool changed = false; registry.ClearDlc(); + var testDlc = TestDlcScan(); foreach (var i in testDlc) { + if (!changed + && (!dlc.TryGetValue(i.Key, out foundVer) + || foundVer != i.Value)) + { + changed = true; + } registry.RegisterDlc(i.Key, i.Value); } + var wellKnownDlc = WellKnownDlcScan(); foreach (var i in wellKnownDlc) { + if (!changed + && (!dlc.TryGetValue(i.Key, out foundVer) + || foundVer != i.Value)) + { + changed = true; + } registry.RegisterDlc(i.Key, i.Value); } + + // Check if anything got removed + if (!changed) + { + foreach (var i in dlc) + { + if (!registry.InstalledDlc.TryGetValue(i.Key, out foundVer) + || foundVer != i.Value) + { + changed = true; + break; + } + } + } + return changed; } private Dictionary TestDlcScan() diff --git a/GUI/MainRepo.cs b/GUI/MainRepo.cs index 2fc34454d7..36664750e8 100644 --- a/GUI/MainRepo.cs +++ b/GUI/MainRepo.cs @@ -30,8 +30,6 @@ public void UpdateRepo() { tabController.RenameTab("WaitTabPage", "Updating repositories"); - CurrentInstance.ScanGameData(); - try { m_UpdateRepoWorker.RunWorkerAsync(); @@ -65,6 +63,9 @@ private void UpdateRepo(object sender, DoWorkEventArgs e) { try { + AddStatusMessage("Scanning GameData for DLCs and manually installed modules..."); + bool scanChanged = CurrentInstance.ScanGameData(); + AddStatusMessage("Updating repositories..."); // Note the current mods' compatibility for the NewlyCompatible filter @@ -80,6 +81,10 @@ private void UpdateRepo(object sender, DoWorkEventArgs e) RepoUpdateResult result = Repo.UpdateAllRepositories( RegistryManager.Instance(CurrentInstance), CurrentInstance, Manager.Cache, GUI.user); + if (result == RepoUpdateResult.NoChanges && scanChanged) + { + result = RepoUpdateResult.Updated; + } e.Result = new KeyValuePair>( result, oldModules); }