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

Fix issues when provides is removed #2740

Merged
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
270 changes: 140 additions & 130 deletions Cmdline/Action/Install.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using log4net;

namespace CKAN.CmdLine
Expand Down Expand Up @@ -125,161 +127,169 @@ public int RunCommand(CKAN.KSP ksp, object raw_options)
install_ops.without_enforce_consistency = true;
}

// Install everything requested. :)
try
{
var installer = ModuleInstaller.GetInstance(ksp, manager.Cache, user);
installer.InstallList(options.modules, install_ops);
user.RaiseMessage("\r\n");
}
catch (DependencyNotSatisfiedKraken ex)
IRegistryQuerier registry = RegistryManager.Instance(ksp).registry;
List<CkanModule> modules = options.modules
.Select(id => registry.LatestAvailable(id, ksp.VersionCriteria()))
.ToList();

for (bool done = false; !done; )
{
if (ex.version == null)
// Install everything requested. :)
try
{
user.RaiseMessage("{0} requires {1} but it is not listed in the index, or not available for your version of KSP.", ex.parent, ex.module);
var installer = ModuleInstaller.GetInstance(ksp, manager.Cache, user);
installer.InstallList(modules, install_ops);
user.RaiseMessage("\r\n");
done = true;
}
else
catch (DependencyNotSatisfiedKraken ex)
{
user.RaiseMessage("{0} requires {1} {2} but it is not listed in the index, or not available for your version of KSP.", ex.parent, ex.module, ex.version);
if (ex.version == null)
{
user.RaiseMessage("{0} requires {1} but it is not listed in the index, or not available for your version of KSP.", ex.parent, ex.module);
}
else
{
user.RaiseMessage("{0} requires {1} {2} but it is not listed in the index, or not available for your version of KSP.", ex.parent, ex.module, ex.version);
}
user.RaiseMessage("If you're lucky, you can do a `ckan update` and try again.");
user.RaiseMessage("Try `ckan install --no-recommends` to skip installation of recommended modules.");
user.RaiseMessage("Or `ckan install --allow-incompatible` to ignore module compatibility.");
return Exit.ERROR;
}
user.RaiseMessage("If you're lucky, you can do a `ckan update` and try again.");
user.RaiseMessage("Try `ckan install --no-recommends` to skip installation of recommended modules.");
user.RaiseMessage("Or `ckan install --allow-incompatible` to ignore module compatibility.");
return Exit.ERROR;
}
catch (ModuleNotFoundKraken ex)
{
if (ex.version == null)
catch (ModuleNotFoundKraken ex)
{
user.RaiseMessage("Module {0} required but it is not listed in the index, or not available for your version of KSP.", ex.module);
if (ex.version == null)
{
user.RaiseMessage("Module {0} required but it is not listed in the index, or not available for your version of KSP.", ex.module);
}
else
{
user.RaiseMessage("Module {0} {1} required but it is not listed in the index, or not available for your version of KSP.", ex.module, ex.version);
}
user.RaiseMessage("If you're lucky, you can do a `ckan update` and try again.");
user.RaiseMessage("Try `ckan install --no-recommends` to skip installation of recommended modules.");
user.RaiseMessage("Or `ckan install --allow-incompatible` to ignore module compatibility.");
return Exit.ERROR;
}
else
catch (BadMetadataKraken ex)
{
user.RaiseMessage("Module {0} {1} required but it is not listed in the index, or not available for your version of KSP.", ex.module, ex.version);
user.RaiseMessage("Bad metadata detected for module {0}.", ex.module);
user.RaiseMessage(ex.Message);
return Exit.ERROR;
}
user.RaiseMessage("If you're lucky, you can do a `ckan update` and try again.");
user.RaiseMessage("Try `ckan install --no-recommends` to skip installation of recommended modules.");
user.RaiseMessage("Or `ckan install --allow-incompatible` to ignore module compatibility.");
return Exit.ERROR;
}
catch (BadMetadataKraken ex)
{
user.RaiseMessage("Bad metadata detected for module {0}.", ex.module);
user.RaiseMessage(ex.Message);
return Exit.ERROR;
}
catch (TooManyModsProvideKraken ex)
{
// Request the user selects one of the mods.
string[] mods = new string[ex.modules.Count];

for (int i = 0; i < ex.modules.Count; i++)
catch (TooManyModsProvideKraken ex)
{
mods[i] = String.Format("{0} ({1})", ex.modules[i].identifier, ex.modules[i].name);
}
// Request the user selects one of the mods.
string[] mods = new string[ex.modules.Count];

for (int i = 0; i < ex.modules.Count; i++)
{
mods[i] = String.Format("{0} ({1})", ex.modules[i].identifier, ex.modules[i].name);
}

string message = String.Format("Too many mods provide {0}. Please pick from the following:\r\n", ex.requested);
string message = String.Format("Too many mods provide {0}. Please pick from the following:\r\n", ex.requested);

int result;
int result;

try
{
result = user.RaiseSelectionDialog(message, mods);
try
{
result = user.RaiseSelectionDialog(message, mods);
}
catch (Kraken e)
{
user.RaiseMessage(e.Message);

return Exit.ERROR;
}

if (result < 0)
{
user.RaiseMessage(String.Empty); // Looks tidier.

return Exit.ERROR;
}

// Add the module to the list.
modules.Add(ex.modules[result]);
// DON'T return so we can loop around and try again
}
catch (Kraken e)
catch (FileExistsKraken ex)
{
user.RaiseMessage(e.Message);
if (ex.owningModule != null)
{
user.RaiseMessage(
"\r\nOh no! We tried to overwrite a file owned by another mod!\r\n"+
"Please try a `ckan update` and try again.\r\n\r\n"+
"If this problem re-occurs, then it maybe a packaging bug.\r\n"+
"Please report it at:\r\n\r\n" +
"https://github.com/KSP-CKAN/NetKAN/issues/new\r\n\r\n" +
"Please including the following information in your report:\r\n\r\n" +
"File : {0}\r\n" +
"Installing Mod : {1}\r\n" +
"Owning Mod : {2}\r\n" +
"CKAN Version : {3}\r\n",
ex.filename, ex.installingModule, ex.owningModule,
Meta.GetVersion(VersionFormat.Full)
);
}
else
{
user.RaiseMessage(
"\r\n\r\nOh no!\r\n\r\n"+
"It looks like you're trying to install a mod which is already installed,\r\n"+
"or which conflicts with another mod which is already installed.\r\n\r\n"+
"As a safety feature, the CKAN will *never* overwrite or alter a file\r\n"+
"that it did not install itself.\r\n\r\n"+
"If you wish to install {0} via the CKAN,\r\n"+
"then please manually uninstall the mod which owns:\r\n\r\n"+
"{1}\r\n\r\n"+"and try again.\r\n",
ex.installingModule, ex.filename
);
}

user.RaiseMessage("Your GameData has been returned to its original state.\r\n");
return Exit.ERROR;
}

if (result < 0)
catch (InconsistentKraken ex)
{
user.RaiseMessage(String.Empty); // Looks tidier.

// The prettiest Kraken formats itself for us.
user.RaiseMessage(ex.InconsistenciesPretty);
user.RaiseMessage("Install canceled. Your files have been returned to their initial state.");
return Exit.ERROR;
}

// Add the module to the list.
options.modules.Add(ex.modules[result].identifier);

return (new Install(manager, user).RunCommand(ksp, options));
}
catch (FileExistsKraken ex)
{
if (ex.owningModule != null)
catch (CancelledActionKraken)
{
user.RaiseMessage(
"\r\nOh no! We tried to overwrite a file owned by another mod!\r\n"+
"Please try a `ckan update` and try again.\r\n\r\n"+
"If this problem re-occurs, then it maybe a packaging bug.\r\n"+
"Please report it at:\r\n\r\n" +
"https://github.com/KSP-CKAN/NetKAN/issues/new\r\n\r\n" +
"Please including the following information in your report:\r\n\r\n" +
"File : {0}\r\n" +
"Installing Mod : {1}\r\n" +
"Owning Mod : {2}\r\n" +
"CKAN Version : {3}\r\n",
ex.filename, ex.installingModule, ex.owningModule,
Meta.GetVersion(VersionFormat.Full)
);
user.RaiseMessage("Installation canceled at user request.");
return Exit.ERROR;
}
else
catch (MissingCertificateKraken kraken)
{
user.RaiseMessage(
"\r\n\r\nOh no!\r\n\r\n"+
"It looks like you're trying to install a mod which is already installed,\r\n"+
"or which conflicts with another mod which is already installed.\r\n\r\n"+
"As a safety feature, the CKAN will *never* overwrite or alter a file\r\n"+
"that it did not install itself.\r\n\r\n"+
"If you wish to install {0} via the CKAN,\r\n"+
"then please manually uninstall the mod which owns:\r\n\r\n"+
"{1}\r\n\r\n"+"and try again.\r\n",
ex.installingModule, ex.filename
);
// Another very pretty kraken.
user.RaiseMessage(kraken.ToString());
return Exit.ERROR;
}
catch (DownloadThrottledKraken kraken)
{
user.RaiseMessage(kraken.ToString());
user.RaiseMessage($"Try the authtoken command. See {kraken.infoUrl} for details.");
return Exit.ERROR;
}
catch (DownloadErrorsKraken)
{
user.RaiseMessage("One or more files failed to download, stopped.");
return Exit.ERROR;
}
catch (ModuleDownloadErrorsKraken kraken)
{
user.RaiseMessage(kraken.ToString());
return Exit.ERROR;
}
catch (DirectoryNotFoundKraken kraken)
{
user.RaiseMessage("\r\n{0}", kraken.Message);
return Exit.ERROR;
}

user.RaiseMessage("Your GameData has been returned to its original state.\r\n");
return Exit.ERROR;
}
catch (InconsistentKraken ex)
{
// The prettiest Kraken formats itself for us.
user.RaiseMessage(ex.InconsistenciesPretty);
user.RaiseMessage("Install canceled. Your files have been returned to their initial state.");
return Exit.ERROR;
}
catch (CancelledActionKraken)
{
user.RaiseMessage("Installation canceled at user request.");
return Exit.ERROR;
}
catch (MissingCertificateKraken kraken)
{
// Another very pretty kraken.
user.RaiseMessage(kraken.ToString());
return Exit.ERROR;
}
catch (DownloadThrottledKraken kraken)
{
user.RaiseMessage(kraken.ToString());
user.RaiseMessage($"Try the authtoken command. See {kraken.infoUrl} for details.");
return Exit.ERROR;
}
catch (DownloadErrorsKraken)
{
user.RaiseMessage("One or more files failed to download, stopped.");
return Exit.ERROR;
}
catch (ModuleDownloadErrorsKraken kraken)
{
user.RaiseMessage(kraken.ToString());
return Exit.ERROR;
}
catch (DirectoryNotFoundKraken kraken)
{
user.RaiseMessage("\r\n{0}", kraken.Message);
return Exit.ERROR;
}

return Exit.OK;
Expand Down
3 changes: 0 additions & 3 deletions GUI/MainDialogs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,6 @@ public async Task<CkanModule> TooManyModsProvide(TooManyModsProvideKraken kraken
tabController.ShowTab("ManageModsTabPage");
});

if (module != null)
MarkModForInstall(module.identifier);

last_mod_to_have_install_toggled.TryPop(out mod);
return module;
}
Expand Down
37 changes: 5 additions & 32 deletions GUI/MainModList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -790,42 +790,15 @@ public async Task<IEnumerable<ModChange>> ComputeChangeSetFromModList(
modules_to_remove.Add(im.Module);
}

bool handled_all_too_many_provides = false;
while (!handled_all_too_many_provides)
{
//Can't await in catch clause - doesn't seem to work in mono. Hence this flag
TooManyModsProvideKraken kraken;
try
{
new RelationshipResolver(
modules_to_install,
modules_to_remove,
RelationshipResolver.DependsOnlyOpts(),
registry, version);
handled_all_too_many_provides = true;
continue;
}
catch (TooManyModsProvideKraken k)
{
kraken = k;
}
//Shouldn't get here unless there is a kraken.
var mod = await too_many_provides(kraken);
if (mod != null)
{
modules_to_install.Add(mod);
}
else
{
//TODO Is could be a new type of Kraken.
throw kraken;
}
}
// Get as many dependencies as we can, but leave decisions and prompts for installation time
RelationshipResolverOptions opts = RelationshipResolver.DependsOnlyOpts();
opts.without_toomanyprovides_kraken = true;
opts.without_enforce_consistency = true;

var resolver = new RelationshipResolver(
modules_to_install,
modules_to_remove,
RelationshipResolver.DependsOnlyOpts(), registry, version);
opts, registry, version);
changeSet.UnionWith(
resolver.ModList()
.Select(m => new ModChange(new GUIMod(m, registry, version), GUIModChangeType.Install, resolver.ReasonFor(m))));
Expand Down
Loading