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

Throw explanatory message when user selects Incompatible mods #2237

Closed
Closed
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: 1 addition & 1 deletion AutoUpdate/CKAN-autoupdate.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand Down
165 changes: 149 additions & 16 deletions CKAN.sln
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
# Visual Studio 2012
VisualStudioVersion = 15.0.27004.2008
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CKAN-core", "Core\CKAN-core.csproj", "{3B9AEA22-FA3B-4E43-9283-EABDD81CF271}"
Expand All @@ -27,18 +27,6 @@ Global
{3B9AEA22-FA3B-4E43-9283-EABDD81CF271}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B9AEA22-FA3B-4E43-9283-EABDD81CF271}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B9AEA22-FA3B-4E43-9283-EABDD81CF271}.Release|Any CPU.Build.0 = Release|Any CPU
{E5B1C768-349E-4DAF-A134-56E4ECF1EEEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5B1C768-349E-4DAF-A134-56E4ECF1EEEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5B1C768-349E-4DAF-A134-56E4ECF1EEEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5B1C768-349E-4DAF-A134-56E4ECF1EEEF}.Release|Any CPU.Build.0 = Release|Any CPU
{E97D81F6-85E2-4F1F-906D-BE21766602E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E97D81F6-85E2-4F1F-906D-BE21766602E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E97D81F6-85E2-4F1F-906D-BE21766602E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E97D81F6-85E2-4F1F-906D-BE21766602E5}.Release|Any CPU.Build.0 = Release|Any CPU
{A79F9D54-315C-472B-928F-713A5860B2BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A79F9D54-315C-472B-928F-713A5860B2BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A79F9D54-315C-472B-928F-713A5860B2BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A79F9D54-315C-472B-928F-713A5860B2BE}.Release|Any CPU.Build.0 = Release|Any CPU
{4336F356-33DB-442A-BF74-5E89AF47A5B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4336F356-33DB-442A-BF74-5E89AF47A5B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4336F356-33DB-442A-BF74-5E89AF47A5B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -47,13 +35,22 @@ Global
{4F41255E-8BC1-465B-82D5-1C5665BC099A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F41255E-8BC1-465B-82D5-1C5665BC099A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F41255E-8BC1-465B-82D5-1C5665BC099A}.Release|Any CPU.Build.0 = Release|Any CPU
{A79F9D54-315C-472B-928F-713A5860B2BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A79F9D54-315C-472B-928F-713A5860B2BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A79F9D54-315C-472B-928F-713A5860B2BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A79F9D54-315C-472B-928F-713A5860B2BE}.Release|Any CPU.Build.0 = Release|Any CPU
{DA5C7023-9A3B-4204-AE2F-BBA6C388B436}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DA5C7023-9A3B-4204-AE2F-BBA6C388B436}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA5C7023-9A3B-4204-AE2F-BBA6C388B436}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA5C7023-9A3B-4204-AE2F-BBA6C388B436}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
{E5B1C768-349E-4DAF-A134-56E4ECF1EEEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5B1C768-349E-4DAF-A134-56E4ECF1EEEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5B1C768-349E-4DAF-A134-56E4ECF1EEEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5B1C768-349E-4DAF-A134-56E4ECF1EEEF}.Release|Any CPU.Build.0 = Release|Any CPU
{E97D81F6-85E2-4F1F-906D-BE21766602E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E97D81F6-85E2-4F1F-906D-BE21766602E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E97D81F6-85E2-4F1F-906D-BE21766602E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E97D81F6-85E2-4F1F-906D-BE21766602E5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
Policies = $0
Expand Down Expand Up @@ -89,5 +86,141 @@ Global
$2.inheritsSet = Mono
$2.inheritsScope = text/x-csharp
$2.scope = text/x-csharp
$0.DotNetNamingPolicy = $3
$3.DirectoryNamespaceAssociation = None
$3.ResourceNamePolicy = FileFormatDefault
$0.StandardHeader = $4
$4.Text =
$4.IncludeInNewFiles = True
$0.NameConventionPolicy = $5
$5.Rules = $6
$6.NamingRule = $7
$7.Name = Namespaces
$7.AffectedEntity = Namespace
$7.VisibilityMask = VisibilityMask
$7.NamingStyle = PascalCase
$7.IncludeInstanceMembers = True
$7.IncludeStaticEntities = True
$6.NamingRule = $8
$8.Name = Types
$8.AffectedEntity = Class, Struct, Enum, Delegate
$8.VisibilityMask = Public
$8.NamingStyle = PascalCase
$8.IncludeInstanceMembers = True
$8.IncludeStaticEntities = True
$6.NamingRule = $9
$9.Name = Interfaces
$9.RequiredPrefixes = $10
$10.String = I
$9.AffectedEntity = Interface
$9.VisibilityMask = Public
$9.NamingStyle = PascalCase
$9.IncludeInstanceMembers = True
$9.IncludeStaticEntities = True
$6.NamingRule = $11
$11.Name = Attributes
$11.RequiredSuffixes = $12
$12.String = Attribute
$11.AffectedEntity = CustomAttributes
$11.VisibilityMask = Public
$11.NamingStyle = PascalCase
$11.IncludeInstanceMembers = True
$11.IncludeStaticEntities = True
$6.NamingRule = $13
$13.Name = Event Arguments
$13.RequiredSuffixes = $14
$14.String = EventArgs
$13.AffectedEntity = CustomEventArgs
$13.VisibilityMask = Public
$13.NamingStyle = PascalCase
$13.IncludeInstanceMembers = True
$13.IncludeStaticEntities = True
$6.NamingRule = $15
$15.Name = Exceptions
$15.RequiredSuffixes = $16
$16.String = Exception
$15.AffectedEntity = CustomExceptions
$15.VisibilityMask = VisibilityMask
$15.NamingStyle = PascalCase
$15.IncludeInstanceMembers = True
$15.IncludeStaticEntities = True
$6.NamingRule = $17
$17.Name = Methods
$17.AffectedEntity = Methods
$17.VisibilityMask = Protected, Public
$17.NamingStyle = PascalCase
$17.IncludeInstanceMembers = True
$17.IncludeStaticEntities = True
$6.NamingRule = $18
$18.Name = Static Readonly Fields
$18.AffectedEntity = ReadonlyField
$18.VisibilityMask = Protected, Public
$18.NamingStyle = PascalCase
$18.IncludeInstanceMembers = False
$18.IncludeStaticEntities = True
$6.NamingRule = $19
$19.Name = Fields
$19.AffectedEntity = Field
$19.VisibilityMask = Protected, Public
$19.NamingStyle = PascalCase
$19.IncludeInstanceMembers = True
$19.IncludeStaticEntities = True
$6.NamingRule = $20
$20.Name = ReadOnly Fields
$20.AffectedEntity = ReadonlyField
$20.VisibilityMask = Protected, Public
$20.NamingStyle = PascalCase
$20.IncludeInstanceMembers = True
$20.IncludeStaticEntities = False
$6.NamingRule = $21
$21.Name = Constant Fields
$21.AffectedEntity = ConstantField
$21.VisibilityMask = Protected, Public
$21.NamingStyle = PascalCase
$21.IncludeInstanceMembers = True
$21.IncludeStaticEntities = True
$6.NamingRule = $22
$22.Name = Properties
$22.AffectedEntity = Property
$22.VisibilityMask = Protected, Public
$22.NamingStyle = PascalCase
$22.IncludeInstanceMembers = True
$22.IncludeStaticEntities = True
$6.NamingRule = $23
$23.Name = Events
$23.AffectedEntity = Event
$23.VisibilityMask = Protected, Public
$23.NamingStyle = PascalCase
$23.IncludeInstanceMembers = True
$23.IncludeStaticEntities = True
$6.NamingRule = $24
$24.Name = Enum Members
$24.AffectedEntity = EnumMember
$24.VisibilityMask = VisibilityMask
$24.NamingStyle = PascalCase
$24.IncludeInstanceMembers = True
$24.IncludeStaticEntities = True
$6.NamingRule = $25
$25.Name = Parameters
$25.AffectedEntity = Parameter
$25.VisibilityMask = VisibilityMask
$25.NamingStyle = CamelCase
$25.IncludeInstanceMembers = True
$25.IncludeStaticEntities = True
$6.NamingRule = $26
$26.Name = Type Parameters
$26.RequiredPrefixes = $27
$27.String = T
$26.AffectedEntity = TypeParameter
$26.VisibilityMask = VisibilityMask
$26.NamingStyle = PascalCase
$26.IncludeInstanceMembers = True
$26.IncludeStaticEntities = True
$0.VersionControlPolicy = $28
$28.inheritsSet = Mono
outputpath = _build\out
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
7 changes: 7 additions & 0 deletions Cmdline/Action/Install.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,13 @@ public int RunCommand(CKAN.KSP ksp, object raw_options)
user.RaiseMessage("Install canceled. Your files have been returned to their initial state.");
return Exit.ERROR;
}
catch (ConflictsKraken ex)
{
// The prettiest Kraken formats itself for us.
user.RaiseMessage(ex.ConflictsPretty);
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.");
Expand Down
2 changes: 1 addition & 1 deletion Cmdline/CKAN-cmdline.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand Down
17 changes: 17 additions & 0 deletions Cmdline/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,23 @@ private static int Scan(CKAN.KSP ksp_instance, IUser user, string next_command =
user.RaiseMessage("Proceeding with {0} in case it fixes it.\r\n", next_command);
}

return Exit.ERROR;
}
catch (ConflictsKraken kraken)
{

if (next_command == null)
{
user.RaiseError(kraken.ConflictsPretty);
user.RaiseError("The repo has not been saved.");
}
else
{
user.RaiseMessage("Preliminary scanning shows that the install is in a inconsistent state.");
user.RaiseMessage("Use ckan.exe scan for more details");
user.RaiseMessage("Proceeding with {0} in case it fixes it.\r\n", next_command);
}

return Exit.ERROR;
}
}
Expand Down
2 changes: 1 addition & 1 deletion ConsoleUI/CKAN-ConsoleUI.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand Down
10 changes: 5 additions & 5 deletions Core/CKAN-core.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand Down Expand Up @@ -44,10 +44,6 @@
<Reference Include="CurlSharp">
<HintPath>..\lib\curlsharp-v0.5.1-2-gd2d5699\CurlSharp.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.5.0, Culture=neutral, PublicKeyToken=9dea7c6e17aa31ff, processorArchitecture=MSIL">
<HintPath>..\_build\lib\nuget\ICSharpCode.SharpZipLib.Patched.0.86.5.1\lib\net20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\_build\lib\nuget\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
</Reference>
Expand All @@ -57,6 +53,10 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Transactions" />
<Reference Include="ICSharpCode.SharpZipLib">
<HintPath>..\_build\lib\nuget\ICSharpCode.SharpZipLib.Patched.0.86.5.1\lib\net20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\_build\meta\GlobalAssemblyVersionInfo.cs">
Expand Down
6 changes: 6 additions & 0 deletions Core/Net/Repo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ You should reinstall them in order to preserve consistency with the repository.
log.WarnFormat("Skipping installation of {0} due to relationship error.", changedIdentifier);
user.RaiseMessage("Skipping installation of {0} due to relationship error.", changedIdentifier);
}
// Thrown when a conflicts relationship is violated
catch (ConflictsKraken)
{
log.WarnFormat("Skipping installation of {0} due to relationship error.", changedIdentifier);
user.RaiseMessage("Skipping installation of {0} due to relationship error.", changedIdentifier);
}
}
}
}
Expand Down
16 changes: 8 additions & 8 deletions Core/Relationships/RelationshipResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ public object Clone()
public class RelationshipResolver
{
// A list of all the mods we're going to install.
private static readonly ILog log = LogManager.GetLogger(typeof (RelationshipResolver));
private readonly Dictionary<string, CkanModule> modlist = new Dictionary<string, CkanModule>();
// The original list of mods selected by the user
private readonly List<CkanModule> user_requested_mods = new List<CkanModule>();

//TODO As the conflict detection gets more advanced there is a greater need to have messages in here
Expand All @@ -102,6 +102,8 @@ public class RelationshipResolver
private readonly RelationshipResolverOptions options;
private readonly HashSet<CkanModule> installed_modules;

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

/// <summary>
/// Creates a new Relationship resolver.
/// </summary>
Expand Down Expand Up @@ -193,6 +195,7 @@ public static RelationshipResolverOptions DefaultOpts()
/// <param name="modules">Modules to attempt to install</param>
public void AddModulesToInstall(IEnumerable<CkanModule> modules)
{
var newConflicts = new List<KeyValuePair<CkanModule, CkanModule>>();
//Count may need to do a full enumeration. Might as well convert to array
var ckan_modules = modules as CkanModule[] ?? modules.ToArray();
log.DebugFormat("Processing relationships for {0} modules", ckan_modules.Count());
Expand All @@ -216,15 +219,13 @@ public void AddModulesToInstall(IEnumerable<CkanModule> modules)
}
else
{
throw new InconsistentKraken(string.Format("{0} conflicts with {1}, can't install both.", module,
listed_mod));
newConflicts.Add(new KeyValuePair<CkanModule, CkanModule>(module, listed_mod));
}
}

}
user_requested_mods.Add(module);
Add(module, new SelectionReason.UserRequested());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels wrong for the GUI to tell me that the mod I just clicked can't be installed, but then to add it to the install list anyway. Can we skip these steps on conflicts?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user may want to deselect the other mod instead. As long as we're telling them what the problem is, flagging the conflicting mods, and disabling the Apply button, I think this is consistent with past behaviour and makes sense. The user has selected this mod because they want it. At this stage, we don't know which of the conflicts they prefer, so better to accept the selection and let them fix it. Otherwise, they may need to scroll to the other mod, unselect it, then scroll back to here and re-select this mod, making far more effort.

}

if (newConflicts.Count() > 0) throw new ConflictsKraken(newConflicts);
// Now that we've already pre-populated the modlist, we can resolve
// the rest of our dependencies.

Expand Down Expand Up @@ -440,8 +441,7 @@ private void ResolveStanza(IEnumerable<RelationshipDescriptor> stanza, Selection
}
else
{
throw new InconsistentKraken(string.Format("{0} conflicts with {1}, can't install both.", conflicting_mod,
candidate));
throw new ConflictsKraken(new KeyValuePair<CkanModule, CkanModule>(candidate, conflicting_mod));
}
}
}
Expand Down
39 changes: 39 additions & 0 deletions Core/Types/Kraken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,45 @@ public override string ToString()
private const string header = "The following inconsistencies were found:\r\n";
}

/// <summary>
/// Thrown if we find ourselves with multiple modules installed which conflict with each other.
/// </summary>
public class ConflictsKraken : Kraken
{
public List<KeyValuePair<CkanModule, CkanModule>> Conflicts = new List<KeyValuePair<CkanModule, CkanModule>>();

public string ConflictsPretty
{
get
{
string message = "The following mod conflicts were found:\r\n";
foreach (KeyValuePair<CkanModule, CkanModule> conflict in Conflicts)
{
message = string.Format("{0}\r\n * {1} conflicts with {2}, can't install both",
message, conflict.Key.name, conflict.Value.name);
}
return message;
}
}

public ConflictsKraken( List<KeyValuePair<CkanModule, CkanModule>> conflicts, Exception innerException = null)
: base(null, innerException)
{
this.Conflicts = conflicts;
}

public ConflictsKraken(KeyValuePair<CkanModule, CkanModule> conflict, Exception innerException = null)
: base(null, innerException)
{
this.Conflicts.Add(conflict);
}

public override string ToString()
{
return ConflictsPretty + StackTrace;
}
}

/// <summary>
/// The terrible state when a file exists when we expect it not to be there.
/// For example, when we install a mod, and it tries to overwrite a file from another mod.
Expand Down
Loading