Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proportional, granular progress updates for installing #4055

Merged
merged 1 commit into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions ConsoleUI/InstallScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,8 @@ public override void Run(ConsoleTheme theme, Action<ConsoleTheme> process = null

HashSet<string> possibleConfigOnlyDirs = null;

ModuleInstaller inst = new ModuleInstaller(manager.CurrentInstance, manager.Cache, this)
{
onReportModInstalled = OnModInstalled
};
ModuleInstaller inst = new ModuleInstaller(manager.CurrentInstance, manager.Cache, this);
inst.onReportModInstalled += OnModInstalled;
if (plan.Remove.Count > 0) {
inst.UninstallList(plan.Remove, ref possibleConfigOnlyDirs, regMgr, true, new List<CkanModule>(plan.Install));
plan.Remove.Clear();
Expand Down Expand Up @@ -103,9 +101,9 @@ public override void Run(ConsoleTheme theme, Action<ConsoleTheme> process = null
}

trans.Complete();
inst.onReportModInstalled -= OnModInstalled;
// Don't let the installer re-use old screen references
inst.User = null;
inst.onReportModInstalled = null;

} catch (CancelledActionKraken) {
// Don't need to tell the user they just cancelled out.
Expand Down
6 changes: 6 additions & 0 deletions Core/Extensions/IOExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ public static void CopyTo(this Stream src,
lastProgressTime = now;
}
}
if (timer != null)
{
timer.Stop();
timer.Close();
timer = null;
}
// Make sure we get a final progress notification after we're done
progress.Report(total);
}
Expand Down
311 changes: 187 additions & 124 deletions Core/ModuleInstaller.cs

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions Core/Registry/Registry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -829,10 +829,10 @@ public List<CkanModule> LatestAvailableWithProvides(
/// Register the supplied module as having been installed, thereby keeping
/// track of its metadata and files.
/// </summary>
public void RegisterModule(CkanModule mod,
IEnumerable<string> absoluteFiles,
GameInstance inst,
bool autoInstalled)
public void RegisterModule(CkanModule mod,
List<string> absoluteFiles,
GameInstance inst,
bool autoInstalled)
{
log.DebugFormat("Registering module {0}", mod);
EnlistWithTransaction();
Expand Down
18 changes: 12 additions & 6 deletions Core/Repositories/ProgressFilesOffsetsToPercent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ public ProgressFilesOffsetsToPercent(IProgress<int> percentProgress,
/// <param name="currentFileOffset">How far into the current file we are</param>
public void Report(long currentFileOffset)
{
var percent = basePercent + (int)(100 * currentFileOffset / totalSize);
// Only report each percentage once, to avoid spamming UI calls
if (percent > lastPercent)
if (totalSize > 0)
{
percentProgress.Report(percent);
lastPercent = percent;
var percent = basePercent + (int)(100 * currentFileOffset / totalSize);
// Only report each percentage once, to avoid spamming UI calls
if (percent > lastPercent)
{
percentProgress.Report(percent);
lastPercent = percent;
}
}
}

Expand All @@ -44,7 +47,10 @@ public void Report(long currentFileOffset)
public void NextFile()
{
doneSize += sizes[currentIndex];
basePercent = (int)(100 * doneSize / totalSize);
if (totalSize > 0)
{
basePercent = (int)(100 * doneSize / totalSize);
}
++currentIndex;
if (basePercent > lastPercent)
{
Expand Down
7 changes: 5 additions & 2 deletions Core/Repositories/ProgressScalePercentsByFileSize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public ProgressScalePercentsByFileSizes(IProgress<int> percentProgress,
/// <param name="currentFilePercent">How far into the current file we are</param>
public void Report(int currentFilePercent)
{
if (basePercent < 100 && currentIndex < sizes.Length)
if (basePercent < 100 && currentIndex < sizes.Length && totalSize > 0)
{
var percent = basePercent + (int)(currentFilePercent * sizes[currentIndex] / totalSize);
// Only report each percentage once, to avoid spamming UI calls
Expand All @@ -47,7 +47,10 @@ public void Report(int currentFilePercent)
public void NextFile()
{
doneSize += sizes[currentIndex];
basePercent = (int)(100 * doneSize / totalSize);
if (totalSize > 0)
{
basePercent = (int)(100 * doneSize / totalSize);
}
++currentIndex;
if (basePercent > lastPercent)
{
Expand Down
4 changes: 2 additions & 2 deletions Tests/CmdLine/UpgradeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public void RunCommand_IdentifierEqualsVersionSyntax_UpgradesToCorrectVersion(
regMgr.registry.RepositoriesAdd(repo.repo);
var fromModule = regMgr.registry.GetModuleByVersion(identifier, fromVersion);
var toModule = regMgr.registry.GetModuleByVersion(identifier, toVersion);
regMgr.registry.RegisterModule(fromModule, Enumerable.Empty<string>(), inst.KSP, false);
regMgr.registry.RegisterModule(fromModule, new List<string>(), inst.KSP, false);
manager.Cache.Store(toModule, TestData.DogeCoinFlagZip(), null);
var opts = new UpgradeOptions()
{
Expand Down Expand Up @@ -598,7 +598,7 @@ public void RunCommand_VersionDependsUpgrade_UpgradesCorrectly(string descript
foreach (var fromModule in instMods)
{
regMgr.registry.RegisterModule(fromModule,
Enumerable.Empty<string>(),
new List<string>(),
inst.KSP, false);
}
// Pre-store mods that might be installed
Expand Down
18 changes: 9 additions & 9 deletions Tests/Core/ModuleInstallerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ public void DontOverWrite_208()

Assert.Throws<FileExistsKraken>(delegate
{
ModuleInstaller.CopyZipEntry(zipfile, entry, tmpfile, false);
ModuleInstaller.CopyZipEntry(zipfile, entry, tmpfile, false, null);
});

// Cleanup
Expand Down Expand Up @@ -357,7 +357,7 @@ private string CopyDogeFromZip()

// We have to delete our temporary file, as CZE refuses to overwrite; huzzah!
File.Delete(tmpfile);
ModuleInstaller.CopyZipEntry(zipfile, entry, tmpfile, false);
ModuleInstaller.CopyZipEntry(zipfile, entry, tmpfile, false, null);

return tmpfile;
}
Expand Down Expand Up @@ -662,7 +662,7 @@ public void GroupFilesByRemovable_WithFiles_CorrectOutput(string relRoot,
var registry = RegistryManager.Instance(inst.KSP, repoData.Manager).registry;
// Make files to be registered to another mod
var absFiles = registeredFiles.Select(f => inst.KSP.ToAbsoluteGameDir(f))
.ToArray();
.ToList();
foreach (var absPath in absFiles)
{
Directory.CreateDirectory(Path.GetDirectoryName(absPath));
Expand Down Expand Up @@ -874,7 +874,7 @@ public void Replace_WithCompatibleModule_Succeeds()
var downloader = new NetAsyncModulesDownloader(nullUser, manager.Cache);

// Act
registry.RegisterModule(replaced, Enumerable.Empty<string>(), inst.KSP, false);
registry.RegisterModule(replaced, new List<string>(), inst.KSP, false);
manager.Cache.Store(replaced, TestData.DogeCoinFlagZip(), new Progress<long>(bytes => {}));
var replacement = querier.GetReplacement(replaced.identifier,
new GameVersionCriteria(new GameVersion(1, 12)));
Expand Down Expand Up @@ -940,7 +940,7 @@ public void Replace_WithIncompatibleModule_Fails()
var downloader = new NetAsyncModulesDownloader(nullUser, manager.Cache);

// Act
registry.RegisterModule(replaced, Enumerable.Empty<string>(), inst.KSP, false);
registry.RegisterModule(replaced, new List<string>(), inst.KSP, false);
manager.Cache.Store(replaced, TestData.DogeCoinFlagZip(), new Progress<long>(bytes => {}));
var replacement = querier.GetReplacement(replaced.identifier,
new GameVersionCriteria(new GameVersion(1, 11)));
Expand Down Expand Up @@ -1006,14 +1006,14 @@ public void UninstallList_WithAutoInst_RemovesAutoRemovable(string[] regularMods
foreach (var m in regularMods)
{
registry.RegisterModule(CkanModule.FromJson(m),
Enumerable.Empty<string>(),
new List<string>(),
inst.KSP,
false);
}
foreach (var m in autoInstMods)
{
registry.RegisterModule(CkanModule.FromJson(m),
Enumerable.Empty<string>(),
new List<string>(),
inst.KSP,
true);
}
Expand Down Expand Up @@ -1098,15 +1098,15 @@ public void Upgrade_WithAutoInst_RemovesAutoRemovable(string[] regularMods,
if (!querier.IsInstalled(module.identifier, false))
{
registry.RegisterModule(module,
Enumerable.Empty<string>(),
new List<string>(),
inst.KSP,
false);
}
}
foreach (var m in autoInstMods)
{
registry.RegisterModule(CkanModule.FromJson(m),
Enumerable.Empty<string>(),
new List<string>(),
inst.KSP,
true);
}
Expand Down
19 changes: 9 additions & 10 deletions Tests/Core/Registry/Registry.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using System.IO;
using System.Transactions;
using System.Collections.Generic;
Expand Down Expand Up @@ -316,8 +315,8 @@ public void HasUpdate_OtherModDependsOnCurrent_ReturnsFalse()
CkanModule dependingMod = registry.GetModuleByVersion("DependingMod", "1.0");

GameInstance gameInst = gameInstWrapper.KSP;
registry.RegisterModule(olderDepMod, Array.Empty<string>(), gameInst, false);
registry.RegisterModule(dependingMod, Array.Empty<string>(), gameInst, false);
registry.RegisterModule(olderDepMod, new List<string>(), gameInst, false);
registry.RegisterModule(dependingMod, new List<string>(), gameInst, false);
GameVersionCriteria crit = new GameVersionCriteria(olderDepMod.ksp_version);

// Act
Expand Down Expand Up @@ -420,7 +419,7 @@ public void TxEmbeddedCommit()
using (var tScope = new TransactionScope())
{
reg = CKAN.Registry.Empty();
reg.RegisterModule(module, Enumerable.Empty<string>(),
reg.RegisterModule(module, new List<string>(),
gameInstWrapper.KSP, false);

CollectionAssert.AreEqual(
Expand Down Expand Up @@ -451,7 +450,7 @@ public void TxCommit()
using (var gameInstWrapper = new DisposableKSP())
using (var tScope = new TransactionScope())
{
registry.RegisterModule(module, Enumerable.Empty<string>(),
registry.RegisterModule(module, new List<string>(),
gameInstWrapper.KSP, false);

CollectionAssert.AreEqual(
Expand Down Expand Up @@ -481,7 +480,7 @@ public void TxRollback()
""version"": ""1.0"",
""download"": ""https://github.com/""
}");
registry.RegisterModule(module, Enumerable.Empty<string>(),
registry.RegisterModule(module, new List<string>(),
gameInstWrapper.KSP, false);

CollectionAssert.AreEqual(
Expand Down Expand Up @@ -515,7 +514,7 @@ public void TxNested()
""version"": ""1.0"",
""download"": ""https://github.com/""
}");
registry.RegisterModule(module, Enumerable.Empty<string>(),
registry.RegisterModule(module, new List<string>(),
gameInstWrapper.KSP, false);

using (var tScope2 = new TransactionScope(TransactionScopeOption.RequiresNew))
Expand All @@ -528,7 +527,7 @@ public void TxNested()
""version"": ""1.0"",
""download"": ""https://github.com/""
}");
registry.RegisterModule(module2, Enumerable.Empty<string>(),
registry.RegisterModule(module2, new List<string>(),
gameInstWrapper.KSP, false);
});
tScope2.Complete();
Expand All @@ -553,7 +552,7 @@ public void TxAmbient()
""version"": ""1.0"",
""download"": ""https://github.com/""
}");
registry.RegisterModule(module, Enumerable.Empty<string>(),
registry.RegisterModule(module, new List<string>(),
gameInstWrapper.KSP, false);

using (var tScope2 = new TransactionScope())
Expand All @@ -566,7 +565,7 @@ public void TxAmbient()
""version"": ""1.0"",
""download"": ""https://github.com/""
}");
registry.RegisterModule(module2, Enumerable.Empty<string>(),
registry.RegisterModule(module2, new List<string>(),
gameInstWrapper.KSP, false);
});
tScope2.Complete();
Expand Down
2 changes: 1 addition & 1 deletion Tests/Core/Registry/RegistryManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ public void ScanUnmanagedFiles_WithDLLs_FindsUnregisteredOnly(string[] registere
var regMgr = RegistryManager.Instance(gameInst, repoData.Manager);
var registry = regMgr.registry;
var absReg = registered.Select(p => gameInst.ToAbsoluteGameDir(p))
.ToArray();
.ToList();
var absUnreg = unregistered.Select(p => gameInst.ToAbsoluteGameDir(p))
.ToArray();

Expand Down
6 changes: 3 additions & 3 deletions Tests/Core/Relationships/RelationshipResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ public void ModList_WithInstalledModules_ContainsThemWithReasonInstalled()
var registry = new CKAN.Registry(repoData.Manager, repo.repo);
var list = new List<CkanModule> { mod_a };

registry.RegisterModule(mod_a, Array.Empty<string>(), null, false);
registry.RegisterModule(mod_a, new List<string>(), null, false);

var relationship_resolver = new RelationshipResolver(
list, null, options, registry, null);
Expand Down Expand Up @@ -1036,8 +1036,8 @@ public void UninstallingConflictingModule_InstallingRecursiveDependencies_Resolv
var registry = new CKAN.Registry(repoData.Manager, repo.repo);

// Start with eve and eveDefaultConfig installed
registry.RegisterModule(eve, Array.Empty<string>(), ksp.KSP, false);
registry.RegisterModule(eveDefaultConfig, Array.Empty<string>(), ksp.KSP, false);
registry.RegisterModule(eve, new List<string>(), ksp.KSP, false);
registry.RegisterModule(eveDefaultConfig, new List<string>(), ksp.KSP, false);

Assert.DoesNotThrow(() => registry.CheckSanity());

Expand Down
2 changes: 1 addition & 1 deletion Tests/GUI/Model/GUIMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public void HasUpdate_UpdateAvailable_ReturnsTrue()
{
var registry = new Registry(repoData.Manager, repo.repo);

registry.RegisterModule(old_version, Enumerable.Empty<string>(), null, false);
registry.RegisterModule(old_version, new List<string>(), null, false);
var upgradeableGroups = registry.CheckUpgradeable(tidy.KSP.VersionCriteria(),
new HashSet<string>());

Expand Down
2 changes: 1 addition & 1 deletion Tests/GUI/Model/ModList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public void InstallAndSortByCompat_WithAnyCompat_NoCrash()

// Install module and set it as pre-installed
manager.Cache.Store(TestData.DogeCoinFlag_101_module(), TestData.DogeCoinFlagZip(), new Progress<long>(bytes => {}));
registry.RegisterModule(anyVersionModule, Array.Empty<string>(), instance.KSP, false);
registry.RegisterModule(anyVersionModule, new List<string>(), instance.KSP, false);

HashSet<string> possibleConfigOnlyDirs = null;
installer.InstallList(
Expand Down
Loading