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

Auto-uninstall auto-installed modules #2753

Merged
merged 1 commit into from
May 7, 2019
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
2 changes: 2 additions & 0 deletions Cmdline/Action/AuthToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public AuthToken() { }
/// <summary>
/// Run the subcommand
/// </summary>
/// <param name="mgr">Manager to provide game instances</param>
/// <param name="opts">Command line parameters paritally handled by parser</param>
/// <param name="unparsed">Command line parameters not yet handled by parser</param>
/// <returns>
/// Exit code
Expand Down
21 changes: 11 additions & 10 deletions Cmdline/Action/List.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public int RunCommand(CKAN.KSP ksp, object raw_options)
log.DebugFormat("Check if upgrades are available for {0}", mod.Key);
CkanModule latest = registry.LatestAvailable(mod.Key, ksp.VersionCriteria());
CkanModule current = registry.GetInstalledVersion(mod.Key);
InstalledModule inst = registry.InstalledModule(mod.Key);

if (latest == null)
{
Expand All @@ -80,13 +81,13 @@ public int RunCommand(CKAN.KSP ksp, object raw_options)
bullet = "X";
if ( current == null ) log.DebugFormat( " {0} installed version not found in registry", mod.Key);

//Check if mod is replaceable
if ( current.replaced_by != null )
// Check if mod is replaceable
if (current.replaced_by != null)
{
ModuleReplacement replacement = registry.GetReplacement(mod.Key, ksp.VersionCriteria());
if ( replacement != null )
if (replacement != null)
{
//Replaceable!
// Replaceable!
bullet = ">";
modInfo = string.Format("{0} > {1} {2}", modInfo, replacement.ReplaceWith.name, replacement.ReplaceWith.version);
}
Expand All @@ -96,14 +97,14 @@ public int RunCommand(CKAN.KSP ksp, object raw_options)
{
// Up to date
log.InfoFormat("Latest {0} is {1}", mod.Key, latest.version);
bullet = "-";
//Check if mod is replaceable
if ( current.replaced_by != null )
bullet = (inst?.AutoInstalled ?? false) ? "+" : "-";
// Check if mod is replaceable
if (current.replaced_by != null)
{
ModuleReplacement replacement = registry.GetReplacement(latest.identifier, ksp.VersionCriteria());
if ( replacement != null )
if (replacement != null)
{
//Replaceable!
// Replaceable!
bullet = ">";
modInfo = string.Format("{0} > {1} {2}", modInfo, replacement.ReplaceWith.name, replacement.ReplaceWith.version);
}
Expand Down Expand Up @@ -134,7 +135,7 @@ public int RunCommand(CKAN.KSP ksp, object raw_options)

if (!(options.porcelain) && exportFileType == null)
{
user.RaiseMessage("\r\nLegend: -: Up to date. X: Incompatible. ^: Upgradable. >: Replaceable\r\n A: Autodetected. ?: Unknown. *: Broken. ");
user.RaiseMessage("\r\nLegend: -: Up to date. +:Auto-installed. X: Incompatible. ^: Upgradable. >: Replaceable\r\n A: Autodetected. ?: Unknown. *: Broken. ");
// Broken mods are in a state that CKAN doesn't understand, and therefore can't handle automatically
}

Expand Down
158 changes: 158 additions & 0 deletions Cmdline/Action/Mark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
using System.Collections.Generic;
using CommandLine;
using CommandLine.Text;
using log4net;

namespace CKAN.CmdLine
{
/// <summary>
/// Subcommand for setting flags on modules,
/// currently the auto-installed flag
/// </summary>
public class Mark : ISubCommand
{
/// <summary>
/// Initialize the subcommand
/// </summary>
public Mark() { }

/// <summary>
/// Run the subcommand
/// </summary>
/// <param name="mgr">Manager to provide game instances</param>
/// <param name="opts">Command line parameters paritally handled by parser</param>
/// <param name="unparsed">Command line parameters not yet handled by parser</param>
/// <returns>
/// Exit code
/// </returns>
public int RunSubCommand(KSPManager mgr, CommonOptions opts, SubCommandOptions unparsed)
{
string[] args = unparsed.options.ToArray();
int exitCode = Exit.OK;
// Parse and process our sub-verbs
Parser.Default.ParseArgumentsStrict(args, new MarkSubOptions(), (string option, object suboptions) =>
{
// ParseArgumentsStrict calls us unconditionally, even with bad arguments
if (!string.IsNullOrEmpty(option) && suboptions != null)
{
CommonOptions options = (CommonOptions)suboptions;
options.Merge(opts);
user = new ConsoleUser(options.Headless);
manager = mgr ?? new KSPManager(user);
exitCode = options.Handle(manager, user);
if (exitCode != Exit.OK)
return;

switch (option)
{
case "auto":
exitCode = MarkAuto((MarkAutoOptions)suboptions, true, option, "auto-installed");
break;

case "user":
exitCode = MarkAuto((MarkAutoOptions)suboptions, false, option, "user-selected");
break;

default:
user.RaiseMessage("Unknown command: mark {0}", option);
exitCode = Exit.BADOPT;
break;
}
}
}, () => { exitCode = MainClass.AfterHelp(); });
return exitCode;
}

private int MarkAuto(MarkAutoOptions opts, bool value, string verb, string descrip)
{
if (opts.modules.Count < 1)
{
user.RaiseMessage("Usage: ckan mark {0} Mod [Mod2 ...]", verb);
return Exit.BADOPT;
}

int exitCode = opts.Handle(manager, user);
if (exitCode != Exit.OK)
{
return exitCode;
}

var ksp = MainClass.GetGameInstance(manager);
var regMgr = RegistryManager.Instance(ksp);
bool needSave = false;
Search.AdjustModulesCase(ksp, opts.modules);
foreach (string id in opts.modules)
{
InstalledModule im = regMgr.registry.InstalledModule(id);
if (im == null)
{
user.RaiseError("{0} is not installed.", id);
}
else if (im.AutoInstalled == value)
{
user.RaiseError("{0} is already marked as {1}.", id, descrip);
}
else
{
user.RaiseMessage("Marking {0} as {1}...", id, descrip);
im.AutoInstalled = value;
needSave = true;
}
}
if (needSave)
{
regMgr.Save(false);
user.RaiseMessage("Changes made!");
}
return Exit.OK;
}

private KSPManager manager { get; set; }
private IUser user { get; set; }

private static readonly ILog log = LogManager.GetLogger(typeof(Mark));
}

internal class MarkSubOptions : VerbCommandOptions
{
[VerbOption("auto", HelpText = "Mark modules as auto installed")]
public MarkAutoOptions MarkAutoOptions { get; set; }

[VerbOption("user", HelpText = "Mark modules as user selected (opposite of auto installed)")]
public MarkAutoOptions MarkUserOptions { get; set; }

[HelpVerbOption]
public string GetUsage(string verb)
{
HelpText ht = HelpText.AutoBuild(this, verb);
// Add a usage prefix line
ht.AddPreOptionsLine(" ");
if (string.IsNullOrEmpty(verb))
{
ht.AddPreOptionsLine("ckan mark - Edit flags on modules");
ht.AddPreOptionsLine($"Usage: ckan mark <command> [options]");
}
else
{
ht.AddPreOptionsLine("ksp " + verb + " - " + GetDescription(verb));
switch (verb)
{
case "auto":
ht.AddPreOptionsLine($"Usage: ckan mark {verb} [options] Mod [Mod2 ...]");
break;

case "user":
ht.AddPreOptionsLine($"Usage: ckan mark {verb} [options] Mod [Mod2 ...]");
break;
}
}
return ht;
}
}

internal class MarkAutoOptions : InstanceSpecificOptions
{
[ValueList(typeof(List<string>))]
public List<string> modules { get; set; }
}
}
1 change: 1 addition & 0 deletions Cmdline/CKAN-cmdline.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<Compile Include="Action\ISubCommand.cs" />
<Compile Include="Action\KSP.cs" />
<Compile Include="Action\List.cs" />
<Compile Include="Action\Mark.cs" />
<Compile Include="Action\Remove.cs" />
<Compile Include="Action\Prompt.cs" />
<Compile Include="Action\Repair.cs" />
Expand Down
4 changes: 3 additions & 1 deletion Cmdline/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ public static int Execute(KSPManager manager, CommonOptions opts, string[] args)

case "cache":
return (new Cache()).RunSubCommand(manager, opts, new SubCommandOptions(args));


case "mark":
return (new Mark()).RunSubCommand(manager, opts, new SubCommandOptions(args));
}
}
catch (NoGameInstanceKraken)
Expand Down
3 changes: 3 additions & 0 deletions Cmdline/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ internal class Actions : VerbCommandOptions
[VerbOption("repo", HelpText = "Manage CKAN repositories")]
public SubCommandOptions Repo { get; set; }

[VerbOption("mark", HelpText = "Edit flags on modules")]
public SubCommandOptions Mark { get; set; }

[VerbOption("ksp", HelpText = "Manage KSP installs")]
public SubCommandOptions KSP { get; set; }

Expand Down
10 changes: 6 additions & 4 deletions ConsoleUI/ModListHelpDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public ModListHelpDialog() : base()
symbolTb.AddLine("Status Symbols");
symbolTb.AddLine("==============");
symbolTb.AddLine($"{installed} Installed");
symbolTb.AddLine($"{autoInstalled} Auto-installed");
symbolTb.AddLine($"{upgradable} Upgradeable");
symbolTb.AddLine($"{autodetected} Manually installed");
symbolTb.AddLine($"{replaceable} Replaceable");
Expand Down Expand Up @@ -65,10 +66,11 @@ public ModListHelpDialog() : base()
));
}

private static readonly string installed = Symbols.checkmark;
private static readonly string upgradable = Symbols.greaterEquals;
private static readonly string autodetected = Symbols.infinity;
private static readonly string replaceable = Symbols.doubleGreater;
private static readonly string installed = Symbols.checkmark;
private static readonly string autoInstalled = Symbols.feminineOrdinal;
private static readonly string upgradable = Symbols.greaterEquals;
private static readonly string autodetected = Symbols.infinity;
private static readonly string replaceable = Symbols.doubleGreater;
}

}
68 changes: 47 additions & 21 deletions ConsoleUI/ModListScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,23 @@ public ModListScreen(KSPManager mgr, bool dbg)
}
return true;
});

moduleList.AddTip("F8", "Mark auto-installed",
() => moduleList.Selection != null
&& (!registry.InstalledModule(moduleList.Selection.identifier)?.AutoInstalled ?? false)
);
moduleList.AddTip("F8", "Mark user-selected",
() => moduleList.Selection != null
&& (registry.InstalledModule(moduleList.Selection.identifier)?.AutoInstalled ?? false)
);
moduleList.AddBinding(Keys.F8, (object sender) => {
InstalledModule im = registry.InstalledModule(moduleList.Selection.identifier);
if (im != null) {
im.AutoInstalled = !im.AutoInstalled;
RegistryManager.Instance(manager.CurrentInstance).Save(false);
}
return true;
});

AddTip("F9", "Apply changes", plan.NonEmpty);
AddBinding(Keys.F9, (object sender) => {
Expand Down Expand Up @@ -552,17 +569,18 @@ public string StatusSymbol(CkanModule m)
public static string StatusSymbol(InstallStatus st)
{
switch (st) {
case InstallStatus.Unavailable: return unavailable;
case InstallStatus.Removing: return removing;
case InstallStatus.Upgrading: return upgrading;
case InstallStatus.Upgradeable: return upgradable;
case InstallStatus.Installed: return installed;
case InstallStatus.Installing: return installing;
case InstallStatus.NotInstalled: return notinstalled;
case InstallStatus.AutoDetected: return autodetected;
case InstallStatus.Replaceable: return replaceable;
case InstallStatus.Replacing: return replacing;
default: return "";
case InstallStatus.Unavailable: return unavailable;
case InstallStatus.Removing: return removing;
case InstallStatus.Upgrading: return upgrading;
case InstallStatus.Upgradeable: return upgradable;
case InstallStatus.Installed: return installed;
case InstallStatus.AutoInstalled: return autoInstalled;
case InstallStatus.Installing: return installing;
case InstallStatus.NotInstalled: return notinstalled;
case InstallStatus.AutoDetected: return autodetected;
case InstallStatus.Replaceable: return replaceable;
case InstallStatus.Replacing: return replacing;
default: return "";
}
}

Expand All @@ -589,16 +607,17 @@ private long totalInstalledDownloadSize()
private const int daysTillStale = 7;
private const int daystillVeryStale = 30;

private static readonly string unavailable = "!";
private static readonly string notinstalled = " ";
private static readonly string installed = Symbols.checkmark;
private static readonly string installing = "+";
private static readonly string upgradable = Symbols.greaterEquals;
private static readonly string upgrading = "^";
private static readonly string removing = "-";
private static readonly string autodetected = Symbols.infinity;
private static readonly string replaceable = Symbols.doubleGreater;
private static readonly string replacing = Symbols.plusMinus;
private static readonly string unavailable = "!";
private static readonly string notinstalled = " ";
private static readonly string installed = Symbols.checkmark;
private static readonly string autoInstalled = Symbols.feminineOrdinal;
private static readonly string installing = "+";
private static readonly string upgradable = Symbols.greaterEquals;
private static readonly string upgrading = "^";
private static readonly string removing = "-";
private static readonly string autodetected = Symbols.infinity;
private static readonly string replaceable = Symbols.doubleGreater;
private static readonly string replacing = Symbols.plusMinus;
}

/// <summary>
Expand Down Expand Up @@ -703,6 +722,8 @@ public InstallStatus GetModStatus(KSPManager manager, IRegistryQuerier registry,
return InstallStatus.Replaceable;
} else if (!IsAnyAvailable(registry, identifier)) {
return InstallStatus.Unavailable;
} else if (registry.InstalledModule(identifier)?.AutoInstalled ?? false) {
return InstallStatus.AutoInstalled;
} else {
return InstallStatus.Installed;
}
Expand Down Expand Up @@ -813,6 +834,11 @@ public enum InstallStatus {
/// This mod is installed and not upgradeable or planned to be removed
/// </summary>
Installed,

/// <summary>
/// Like Installed, but can be auto-removed if depending mods are removed
/// </summary>
AutoInstalled,

/// <summary>
/// This mod is not installed but we are planning to install it
Expand Down
7 changes: 7 additions & 0 deletions ConsoleUI/Toolkit/Keys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ public static class Keys {
(System.Char)0, ConsoleKey.F5, false, false, false
);

/// <summary>
/// Representation of F8 for key bindings
/// </summary>
public static readonly ConsoleKeyInfo F8 = new ConsoleKeyInfo(
(System.Char)0, ConsoleKey.F8, false, false, false
);

/// <summary>
/// Representation of F9 for key bindings
/// </summary>
Expand Down
Loading