Skip to content

Commit 92bb2e9

Browse files
committed
Merge #4429 Add tests for ModuleInstaller
2 parents 2aea1b1 + c654be6 commit 92bb2e9

File tree

12 files changed

+687
-130
lines changed

12 files changed

+687
-130
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ All notable changes to this project will be documented in this file.
2929
- [Netkan] Exclude internal .ckan files from `install_size` (#4348 by: HebaruSan)
3030
- [Core] Generate and tidy up XML docs for Core (#4351 by: HebaruSan)
3131
- [Core] Use setter instead of reflection to set max transaction timeout (#4365 by: doinkythederp; reviewed: HebaruSan)
32-
- [Build] Coverage and more tests (#4383, #4396, #4408, #4420, #4422, #4423, #4425, #4426 by: HebaruSan)
32+
- [Build] Coverage and more tests (#4383, #4396, #4408, #4420, #4422, #4423, #4425, #4426, #4429 by: HebaruSan)
3333
- [Multiple] Switch Inflator from Mono to dotnet (#4387 by: HebaruSan)
3434
- [Multiple] Migrate metadata tester from Mono to dotnet (#4390 by: HebaruSan)
3535
- [Multiple] Writethrough when saving files, add Netkan tests (#4392 by: HebaruSan)

Core/Extensions/YamlExtensions.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ namespace CKAN.Extensions
1010
public static class YamlExtensions
1111
{
1212
public static YamlMappingNode[] Parse(string input)
13-
{
14-
return Parse(new StringReader(input));
15-
}
13+
=> Parse(new StringReader(input));
1614

1715
public static YamlMappingNode[] Parse(TextReader input)
1816
{

Core/IO/ModuleInstaller.cs

Lines changed: 41 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,8 @@ private List<string> InstallModule(CkanModule module,
360360

361361
try
362362
{
363-
var dll = registry.DllPath(module.identifier);
364-
if (dll is not null && !string.IsNullOrEmpty(dll))
363+
if (registry.DllPath(module.identifier)
364+
is string { Length: > 0 } dll)
365365
{
366366
// Find where we're installing identifier.optionalversion.dll
367367
// (file name might not be an exact match with manually installed)
@@ -393,22 +393,21 @@ private List<string> InstallModule(CkanModule module,
393393
// Look for overwritable files if session is interactive
394394
if (!User.Headless)
395395
{
396-
var conflicting = FindConflictingFiles(zipfile, files, registry).Memoize();
397-
if (conflicting.Any())
396+
if (FindConflictingFiles(zipfile, files, registry).ToArray()
397+
is (InstallableFile file, bool same)[] { Length: > 0 } conflicting)
398398
{
399-
var fileMsg = conflicting
400-
.OrderBy(c => c.Value)
401-
.Aggregate("", (a, b) =>
402-
$"{a}\r\n- {instance.ToRelativeGameDir(b.Key.destination)} ({(b.Value ? Properties.Resources.ModuleInstallerFileSame : Properties.Resources.ModuleInstallerFileDifferent)})");
403-
if (User.RaiseYesNoDialog(string.Format(
404-
Properties.Resources.ModuleInstallerOverwrite, module.name, fileMsg)))
399+
var fileMsg = string.Join(Environment.NewLine,
400+
conflicting.OrderBy(tuple => tuple.same)
401+
.Select(tuple => $"- {instance.ToRelativeGameDir(tuple.file.destination)} ({(tuple.same ? Properties.Resources.ModuleInstallerFileSame : Properties.Resources.ModuleInstallerFileDifferent)})"));
402+
if (User.RaiseYesNoDialog(string.Format(Properties.Resources.ModuleInstallerOverwrite,
403+
module.name, fileMsg)))
405404
{
406-
DeleteConflictingFiles(conflicting.Select(f => f.Key));
405+
DeleteConflictingFiles(conflicting.Select(tuple => tuple.file));
407406
}
408407
else
409408
{
410-
throw new CancelledActionKraken(string.Format(
411-
Properties.Resources.ModuleInstallerOverwriteCancelled, module.name));
409+
throw new CancelledActionKraken(string.Format(Properties.Resources.ModuleInstallerOverwriteCancelled,
410+
module.name));
412411
}
413412
}
414413
}
@@ -467,27 +466,25 @@ public static bool IsInternalCkan(ZipEntry ze)
467466
/// <returns>
468467
/// List of pairs: Key = file, Value = true if identical, false if different
469468
/// </returns>
470-
private IEnumerable<KeyValuePair<InstallableFile, bool>> FindConflictingFiles(ZipFile zip, IEnumerable<InstallableFile> files, Registry registry)
471-
{
472-
foreach (InstallableFile file in files)
473-
{
474-
if (!file.source.IsDirectory
475-
&& File.Exists(file.destination)
476-
&& registry.FileOwner(instance.ToRelativeGameDir(file.destination)) == null)
477-
{
478-
log.DebugFormat("Comparing {0}", file.destination);
479-
using (Stream zipStream = zip.GetInputStream(file.source))
480-
using (FileStream curFile = new FileStream(file.destination, FileMode.Open, FileAccess.Read))
469+
private IEnumerable<(InstallableFile file, bool same)> FindConflictingFiles(ZipFile zip,
470+
IEnumerable<InstallableFile> files,
471+
Registry registry)
472+
=> files.Where(file => !file.source.IsDirectory
473+
&& File.Exists(file.destination)
474+
&& registry.FileOwner(instance.ToRelativeGameDir(file.destination)) == null)
475+
.Select(file =>
481476
{
482-
yield return new KeyValuePair<InstallableFile, bool>(
483-
file,
484-
file.source.Size == curFile.Length
485-
&& StreamsEqual(zipStream, curFile)
486-
);
487-
}
488-
}
489-
}
490-
}
477+
log.DebugFormat("Comparing {0}", file.destination);
478+
using (Stream zipStream = zip.GetInputStream(file.source))
479+
using (FileStream curFile = new FileStream(file.destination,
480+
FileMode.Open,
481+
FileAccess.Read))
482+
{
483+
return (file,
484+
same: file.source.Size == curFile.Length
485+
&& StreamsEqual(zipStream, curFile));
486+
}
487+
});
491488

492489
/// <summary>
493490
/// Compare the contents of two streams
@@ -745,10 +742,7 @@ public static List<InstallableFile> FindInstallableFiles(CkanModule module, stri
745742
progress?.Report(0);
746743
StreamUtils.Copy(zipStream, writer, buffer,
747744
// This doesn't fire at all if the interval never elapses
748-
(sender, e) =>
749-
{
750-
progress?.Report(e.Processed);
751-
},
745+
(sender, e) => progress?.Report(e.Processed),
752746
UnzipProgressInterval,
753747
entry, "InstallFile");
754748
}
@@ -1073,15 +1067,15 @@ private void Uninstall(string identifier,
10731067
}
10741068
}
10751069

1076-
internal static void GroupFilesByRemovable(string relRoot,
1077-
Registry registry,
1078-
string[] alreadyRemoving,
1079-
IGame game,
1080-
string[] relPaths,
1081-
out string[] removable,
1082-
out string[] notRemovable)
1070+
internal static void GroupFilesByRemovable(string relRoot,
1071+
Registry registry,
1072+
IReadOnlyCollection<string> alreadyRemoving,
1073+
IGame game,
1074+
IReadOnlyCollection<string> relPaths,
1075+
out string[] removable,
1076+
out string[] notRemovable)
10831077
{
1084-
if (relPaths.Length < 1)
1078+
if (relPaths.Count < 1)
10851079
{
10861080
removable = Array.Empty<string>();
10871081
notRemovable = Array.Empty<string>();
@@ -1102,8 +1096,8 @@ internal static void GroupFilesByRemovable(string relRoot,
11021096
.ToDictionary(grp => grp.Key,
11031097
grp => grp.OrderByDescending(f => f.Length)
11041098
.ToArray());
1105-
removable = contents.TryGetValue(true, out string[]? val1) ? val1 : Array.Empty<string>();
1106-
notRemovable = contents.TryGetValue(false, out string[]? val2) ? val2 : Array.Empty<string>();
1099+
removable = contents.GetValueOrDefault(true) ?? Array.Empty<string>();
1100+
notRemovable = contents.GetValueOrDefault(false) ?? Array.Empty<string>();
11071101
log.DebugFormat("Got removable: {0}", string.Join(", ", removable));
11081102
log.DebugFormat("Got notRemovable: {0}", string.Join(", ", notRemovable));
11091103
}

GUI/Controls/EditModSearchDetails.cs

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -68,43 +68,50 @@ public ModSearch CurrentSearch()
6868

6969
public void PopulateSearch(ModSearch? search)
7070
{
71-
FilterByNameTextBox.Text = search?.Name
72-
?? "";
73-
FilterByAuthorTextBox.Text = search?.Authors.Aggregate("", CombinePieces)
74-
?? "";
75-
FilterByDescriptionTextBox.Text = search?.Description
76-
?? "";
77-
FilterByLicenseTextBox.Text = search?.Licenses.Aggregate("", CombinePieces)
78-
?? "";
79-
FilterByLanguageTextBox.Text = search?.Localizations.Aggregate("", CombinePieces)
80-
?? "";
81-
FilterByDependsTextBox.Text = search?.DependsOn.Aggregate("", CombinePieces)
82-
?? "";
83-
FilterByRecommendsTextBox.Text = search?.Recommends.Aggregate("", CombinePieces)
84-
?? "";
85-
FilterBySuggestsTextBox.Text = search?.Suggests.Aggregate("", CombinePieces)
86-
?? "";
87-
FilterByConflictsTextBox.Text = search?.ConflictsWith.Aggregate("", CombinePieces)
88-
?? "";
89-
FilterBySupportsTextBox.Text = search?.Supports.Aggregate("", CombinePieces)
90-
?? "";
91-
FilterByTagsTextBox.Text = search?.TagNames.Aggregate("", CombinePieces)
92-
?? "";
93-
FilterByLabelsTextBox.Text = search?.LabelNames.Aggregate("", CombinePieces)
94-
?? "";
95-
96-
CompatibleToggle.Value = search?.Compatible;
97-
InstalledToggle.Value = search?.Installed;
98-
CachedToggle.Value = search?.Cached;
99-
NewlyCompatibleToggle.Value = search?.NewlyCompatible;
100-
UpgradeableToggle.Value = search?.Upgradeable;
101-
ReplaceableToggle.Value = search?.Replaceable;
71+
if (search == null)
72+
{
73+
FilterByNameTextBox.Text = "";
74+
FilterByAuthorTextBox.Text = "";
75+
FilterByDescriptionTextBox.Text = "";
76+
FilterByLicenseTextBox.Text = "";
77+
FilterByLanguageTextBox.Text = "";
78+
FilterByDependsTextBox.Text = "";
79+
FilterByRecommendsTextBox.Text = "";
80+
FilterBySuggestsTextBox.Text = "";
81+
FilterByConflictsTextBox.Text = "";
82+
FilterBySupportsTextBox.Text = "";
83+
FilterByTagsTextBox.Text = "";
84+
FilterByLabelsTextBox.Text = "";
85+
CompatibleToggle.Value = null;
86+
InstalledToggle.Value = null;
87+
CachedToggle.Value = null;
88+
NewlyCompatibleToggle.Value = null;
89+
UpgradeableToggle.Value = null;
90+
ReplaceableToggle.Value = null;
91+
}
92+
else
93+
{
94+
FilterByNameTextBox.Text = search.Name;
95+
FilterByAuthorTextBox.Text = string.Join(" ", search.Authors);
96+
FilterByDescriptionTextBox.Text = string.Join(" ", search.Description);
97+
FilterByLicenseTextBox.Text = string.Join(" ", search.Licenses);
98+
FilterByLanguageTextBox.Text = string.Join(" ", search.Localizations);
99+
FilterByDependsTextBox.Text = string.Join(" ", search.DependsOn);
100+
FilterByRecommendsTextBox.Text = string.Join(" ", search.Recommends);
101+
FilterBySuggestsTextBox.Text = string.Join(" ", search.Suggests);
102+
FilterByConflictsTextBox.Text = string.Join(" ", search.ConflictsWith);
103+
FilterBySupportsTextBox.Text = string.Join(" ", search.Supports);
104+
FilterByTagsTextBox.Text = string.Join(" ", search.TagNames);
105+
FilterByLabelsTextBox.Text = string.Join(" ", search.LabelNames);
106+
CompatibleToggle.Value = search.Compatible;
107+
InstalledToggle.Value = search.Installed;
108+
CachedToggle.Value = search.Cached;
109+
NewlyCompatibleToggle.Value = search.NewlyCompatible;
110+
UpgradeableToggle.Value = search.Upgradeable;
111+
ReplaceableToggle.Value = search.Replaceable;
112+
}
102113
}
103114

104-
private static string CombinePieces(string joined, string piece)
105-
=> string.IsNullOrEmpty(joined) ? piece
106-
: $"{joined} {piece}";
107-
108115
/// <summary>
109116
/// Override special settings to make this control behave like a dropdown.
110117
/// The "|=" lines are turning ON those flags.

GUI/Controls/ManageMods.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2109,9 +2109,7 @@ public bool AllowClose()
21092109
if (Conflicts != null && Conflicts.Count != 0)
21102110
{
21112111
// Ask if they want to resolve conflicts
2112-
string confDescrip = Conflicts
2113-
.Select(kvp => kvp.Value)
2114-
.Aggregate((a, b) => $"{a}, {b}");
2112+
string confDescrip = string.Join(", ", Conflicts.Select(kvp => kvp.Value));
21152113
if (!Main.Instance?.YesNoDialog(string.Format(Properties.Resources.MainQuitWithConflicts, confDescrip),
21162114
Properties.Resources.MainQuit,
21172115
Properties.Resources.MainGoBack) ?? false)
@@ -2122,11 +2120,9 @@ public bool AllowClose()
21222120
else if (ChangeSet?.Any() ?? false)
21232121
{
21242122
// Ask if they want to discard the change set
2125-
string changeDescrip = ChangeSet
2126-
.GroupBy(ch => ch.ChangeType, ch => ch.Mod.name)
2127-
.Select(grp => $"{grp.Key}: "
2128-
+ grp.Aggregate((a, b) => $"{a}, {b}"))
2129-
.Aggregate((a, b) => $"{a}\r\n{b}");
2123+
string changeDescrip = string.Join(Environment.NewLine,
2124+
ChangeSet.GroupBy(ch => ch.ChangeType, ch => ch.Mod.name)
2125+
.Select(grp => $"{grp.Key}: " + string.Join(", ", grp)));
21302126
if (!Main.Instance?.YesNoDialog(string.Format(Properties.Resources.MainQuitWithUnappliedChanges, changeDescrip),
21312127
Properties.Resources.MainQuit,
21322128
Properties.Resources.MainGoBack) ?? false)

GUI/Main/Main.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -958,9 +958,8 @@ private void LaunchGame(string command)
958958
if (incomp.Count != 0 && CurrentInstance.Version() is GameVersion gv)
959959
{
960960
// Warn that it might not be safe to run game with incompatible modules installed
961-
string incompatDescrip = incomp
962-
.Select(m => $"{m.Module} ({m.Module.CompatibleGameVersions(CurrentInstance.game)})")
963-
.Aggregate((a, b) => $"{a}{Environment.NewLine}{b}");
961+
string incompatDescrip = string.Join(Environment.NewLine,
962+
incomp.Select(m => $"{m.Module} ({m.Module.CompatibleGameVersions(CurrentInstance.game)})"));
964963
var result = SuppressableYesNoDialog(
965964
string.Format(Properties.Resources.MainLaunchWithIncompatible,
966965
incompatDescrip),

0 commit comments

Comments
 (0)