ShipModCatalog.RemovePackage: the one uninstall moves a mod aside to GameData/RemovedMods

Presence under Mods is the only enablement; removal is a move, never a delete,
and moving a package back reinstalls it. Refuses names that are not a package
directory directly under the mods root. Not yet built or run; verify runs at
the end of the cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-16 21:47:38 +02:00
commit e04e247820
3 changed files with 70 additions and 0 deletions

View file

@ -189,6 +189,28 @@ public static class ShipModCatalog
return (composition.Included.Length == 0 ? shippedCatalog : derivedCatalog, composition.Excluded);
}
// The one uninstall: presence under Mods is the only enablement (MR1), so a package leaves by moving, never by deletion,
// to <parent of modsRoot>/RemovedMods/<package> ('<package> (2)' and on when taken). Moving it back reinstalls it.
// Returns the destination. Compose and ResolveCatalog never read RemovedMods.
public static string RemovePackage(string modsRoot, string package)
{
if (string.IsNullOrEmpty(package) || package == "." || package == ".." || package == "(all mods)" ||
package != Path.GetFileName(package) || package.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
throw new ArgumentException("Not a mod package name.", nameof(package));
var source = Path.Combine(Path.GetFullPath(modsRoot), package);
if (!Directory.Exists(source)) throw new DirectoryNotFoundException("The package is not a directory under the mods folder.");
var removed = RemovedRoot(modsRoot);
Directory.CreateDirectory(removed);
var destination = Path.Combine(removed, package);
for (var copy = 2; Directory.Exists(destination) || File.Exists(destination); copy++)
destination = Path.Combine(removed, $"{package} ({copy})");
Directory.Move(source, destination);
return destination;
}
private static string RemovedRoot(string modsRoot) =>
Path.Combine(Path.GetDirectoryName(Path.GetFullPath(modsRoot)), "RemovedMods");
private static Package Bind(HullData hull, ShipAuthoring ship, FactionProductData[] products, string directory, string path)
{
if (!string.Equals(Path.GetFileName(directory), ship.Id, StringComparison.Ordinal))