Skip to content

Commit

Permalink
Support BreakingGround-DLC in instance faking
Browse files Browse the repository at this point in the history
* Redo `ckan ksp fake` command syntax.

* Adjust `CloneFakeKspDialog`

* Extend IDlcDetector with `InstallPath()` and `AllowedOnBaseVersion()`.

* Make `FakeInstance()` a transaction, cover IO operations in `CopyDirectory()` transaction,
    make `KSP.SetupCkanDirectories()` transaction aware.
  • Loading branch information
DasSkelett committed Jun 19, 2019
1 parent 4c09e27 commit c07d880
Show file tree
Hide file tree
Showing 16 changed files with 312 additions and 139 deletions.
74 changes: 57 additions & 17 deletions Cmdline/Action/KSP.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using CKAN.Versioning;
Expand Down Expand Up @@ -54,8 +55,7 @@ public string GetUsage(string verb)
{
// First the commands with three string arguments
case "fake":
ht.AddPreOptionsLine($"Usage: ckan ksp {verb} [options] name path version dlcVersion");
ht.AddPreOptionsLine($"Choose dlcVersion \"none\" if you want no simulated dlc.");
ht.AddPreOptionsLine($"Usage: ckan ksp {verb} [options] name path version [--MakingHistory <version>] [--BreakingGround <version>]");
break;

case "clone":
Expand Down Expand Up @@ -124,8 +124,14 @@ internal class FakeOptions : CommonOptions
[ValueOption(0)] public string name { get; set; }
[ValueOption(1)] public string path { get; set; }
[ValueOption(2)] public string version { get; set; }
[ValueOption(3)] public string dlcVersion { get; set; }
[Option("set-default", DefaultValue = false, HelpText = "Set the new instance to the default one.")] public bool setToDefault { get; set; }

[Option("MakingHistory", DefaultValue = "none", HelpText = "The version of the Making History DLC to be faked.")]
public string makingHistoryVersion { get; set; }
[Option("BreakingGround", DefaultValue = "none", HelpText = "The version of the Breaking Ground DLC to be faked.")]
public string breakingGroundVersion { get; set; }

[Option("set-default", DefaultValue = false, HelpText = "Set the new instance as the default one.")]
public bool setDefault { get; set; }
}

// This is required by ISubCommand
Expand Down Expand Up @@ -508,7 +514,7 @@ private int FakeNewKSPInstall (FakeOptions options)
{
if (options.name == null || options.path == null || options.version == null)
{
User.RaiseMessage("ksp fake <name> <path> <version> [dlcVersion] - argument(s) missing");
User.RaiseMessage("ksp fake <name> <path> <version> [--MakingHistory <version>] [--BreakingGround <version>] - argument(s) missing");
return Exit.BADOPT;
}

Expand All @@ -517,16 +523,35 @@ private int FakeNewKSPInstall (FakeOptions options)
string installName = options.name;
string path = options.path;
KspVersion version;
bool setToDefault = options.setToDefault;
// dlcVersion is null if a user wants no simulated DLC
string dlcVersion;
if (options.dlcVersion == null || options.dlcVersion.ToLower() == "none")
bool setDefault = options.setDefault;

// options.<DLC>Version is "none" if the DLC should not be simulated.
Dictionary<DLC.IDlcDetector, KspVersion> dlcs = new Dictionary<DLC.IDlcDetector, KspVersion>();
if (options.makingHistoryVersion != null && options.makingHistoryVersion.ToLower() != "none")
{
dlcVersion = null;
if (KspVersion.TryParse(options.makingHistoryVersion, out KspVersion ver))
{
dlcs.Add(new DLC.MakingHistoryDlcDetector(), ver);
}
else
{
User.RaiseError("Please check the Making History DLC version argument - Format it like Maj.Min.Patch - e.g. 1.1.0");
User.RaiseMessage("--Error--");
return Exit.BADOPT;
}
}
else
if (options.breakingGroundVersion != null && options.breakingGroundVersion.ToLower() != "none")
{
dlcVersion = options.dlcVersion;
if (KspVersion.TryParse(options.breakingGroundVersion, out KspVersion ver))
{
dlcs.Add(new DLC.BreakingGroundDlcDetector(), ver);
}
else
{
User.RaiseError("Please check the Breaking Ground DLC version argument - Format it like Maj.Min.Patch - e.g. 1.1.0");
User.RaiseMessage("--Error--");
return Exit.BADOPT;
}
}

// Parse the choosen KSP version
Expand All @@ -538,6 +563,7 @@ private int FakeNewKSPInstall (FakeOptions options)
{
// Thrown if there is anything besides numbers and points in the version string or a different syntactic error.
User.RaiseError("Please check the version argument - Format it like Maj.Min.Patch[.Build] - e.g. 1.6.0 or 1.2.2.1622");
User.RaiseMessage("--Error--");
return Exit.BADOPT;
}

Expand All @@ -550,36 +576,50 @@ private int FakeNewKSPInstall (FakeOptions options)
{
User.RaiseError("Couldn't find a valid KSP version for your input.\n" +
"Make sure to enter the at least the version major and minor values in the form Maj.Min - e.g. 1.5");
User.RaiseMessage("--Error--");
return Exit.BADOPT;
}
catch (CancelledActionKraken)
{
User.RaiseError("Selection cancelled! Please call 'ckan ksp fake' again.");
User.RaiseMessage("--Error--");
return Exit.ERROR;
}


User.RaiseMessage(String.Format("Creating new fake KSP install {0} at {1} with version {2}", installName, path, version.ToString()));
log.Debug("Faking instance...");

try
{
// Pass all arguments to CKAN.KSPManager.FakeInstance() and create a new one.
Manager.FakeInstance(installName, path, version, dlcVersion);
if (setToDefault)
Manager.FakeInstance(installName, path, version, dlcs);
if (setDefault)
{
User.RaiseMessage("Setting new instance to default...");
Manager.SetAutoStart(installName);
}
}
catch (BadInstallLocationKraken kraken)
{
// The folder exists and is not empty.
log.Error(kraken);
User.RaiseError(kraken.Message);
User.RaiseMessage("--Error--");
return Exit.ERROR;
}
catch (IncorrectKSPVersionKraken kraken)
{
// Either thrown because the version object was invalid (highly unlikely with RaiseVersionSelectionDialog())
// or because the specified KSP version is too old for one of the DLCs.
User.RaiseError(kraken.Message);
User.RaiseMessage("--Error--");
return Exit.ERROR;
}
catch (NotKSPDirKraken kraken)
{
// Something went wrong adding the new instance to the registry,
// most likely because the newly created directory is not valid.
// most likely because the newly created directory is somehow not valid.
log.Error(kraken);
User.RaiseMessage("--Error--");
return Exit.ERROR;
}
catch (InvalidKSPInstanceKraken)
Expand Down
2 changes: 1 addition & 1 deletion Core/DLC/BreakingGroundDlcDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ namespace CKAN.DLC
public sealed class BreakingGroundDlcDetector : StandardDlcDetectorBase
{
public BreakingGroundDlcDetector()
: base("BreakingGround", "Serenity") { }
: base("BreakingGround", "Serenity", new Versioning.KspVersion(1, 7, 1)) { }
}
}
18 changes: 17 additions & 1 deletion Core/DLC/IDlcDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ namespace CKAN.DLC
/// </summary>
public interface IDlcDetector
{
string IdentifierBaseName { get; }
KspVersion ReleaseGameVersion { get; }

/// <summary>
/// Checks if the relevant DLC is installed in the specific KSP installation.
/// </summary>
Expand Down Expand Up @@ -34,6 +37,19 @@ public interface IDlcDetector
/// </item>
/// </list>
/// </returns>
bool IsInstalled(KSP ksp, out string identifier, out UnmanagedModuleVersion version);
bool IsInstalled (KSP ksp, out string identifier, out UnmanagedModuleVersion version);

/// <summary>
/// Path to the DLC directory relative to GameDir.
/// E.g. GameData/SquadExpansion/Serenity
/// </summary>
/// <returns>The relative path as string.</returns>
string InstallPath ();

/// <summary>
/// Determines whether the DLC is allowed to be installed (or faked)
/// on the specified base version (i.e. the game version of the KSP instance.)
/// </summary>
bool AllowedOnBaseVersion (KspVersion baseVersion);
}
}
2 changes: 1 addition & 1 deletion Core/DLC/MakingHistoryDlcDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace CKAN.DLC
public sealed class MakingHistoryDlcDetector : StandardDlcDetectorBase
{
public MakingHistoryDlcDetector()
: base("MakingHistory", new Dictionary<string, string>()
: base("MakingHistory", new Versioning.KspVersion(1, 4, 1), new Dictionary<string, string>()
{
{ "1.0", "1.0.0" }
}
Expand Down
21 changes: 17 additions & 4 deletions Core/DLC/StandardDlcDetectorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ namespace CKAN.DLC
/// </remarks>
public abstract class StandardDlcDetectorBase : IDlcDetector
{
private readonly string IdentifierBaseName;
public KspVersion ReleaseGameVersion { get; }
public string IdentifierBaseName { get; }

private readonly string DirectoryBaseName;
private readonly Dictionary<string, string> CanonicalVersions;

Expand All @@ -25,10 +27,10 @@ public abstract class StandardDlcDetectorBase : IDlcDetector
RegexOptions.Compiled | RegexOptions.IgnoreCase
);

protected StandardDlcDetectorBase(string identifierBaseName, Dictionary<string, string> canonicalVersions = null)
: this(identifierBaseName, identifierBaseName, canonicalVersions) { }
protected StandardDlcDetectorBase(string identifierBaseName, KspVersion releaseGameVersion, Dictionary<string, string> canonicalVersions = null)
: this(identifierBaseName, identifierBaseName, releaseGameVersion, canonicalVersions) { }

protected StandardDlcDetectorBase(string identifierBaseName, string directoryBaseName, Dictionary<string, string> canonicalVersions = null)
protected StandardDlcDetectorBase(string identifierBaseName, string directoryBaseName, KspVersion releaseGameVersion, Dictionary<string, string> canonicalVersions = null)
{
if (string.IsNullOrWhiteSpace(identifierBaseName))
throw new ArgumentException("Value must be provided.", nameof(identifierBaseName));
Expand All @@ -38,6 +40,7 @@ protected StandardDlcDetectorBase(string identifierBaseName, string directoryBas

IdentifierBaseName = identifierBaseName;
DirectoryBaseName = directoryBaseName;
ReleaseGameVersion = releaseGameVersion;
CanonicalVersions = canonicalVersions ?? new Dictionary<string, string>();
}

Expand Down Expand Up @@ -77,5 +80,15 @@ public virtual bool IsInstalled(KSP ksp, out string identifier, out UnmanagedMod
return false;
}
}

public virtual string InstallPath()
{
return Path.Combine("GameData", "SquadExpansion", DirectoryBaseName);
}

public bool AllowedOnBaseVersion(KspVersion baseVersion)
{
return baseVersion >= ReleaseGameVersion;
}
}
}
8 changes: 6 additions & 2 deletions Core/KSP.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Text.RegularExpressions;
using System.Transactions;
using Autofac;
using ChinhDo.Transactions;
using CKAN.GameVersionProviders;
using CKAN.Versioning;
using log4net;
Expand Down Expand Up @@ -75,11 +76,14 @@ private void SetupCkanDirectories()
{
log.InfoFormat("Initialising {0}", CkanDir());

// TxFileManager knows if we are in a transaction
TxFileManager txFileMgr = new TxFileManager();

if (!Directory.Exists(CkanDir()))
{
User.RaiseMessage("Setting up CKAN for the first time...");
User.RaiseMessage("Creating {0}", CkanDir());
Directory.CreateDirectory(CkanDir());
txFileMgr.CreateDirectory(CkanDir());

User.RaiseMessage("Scanning for installed mods...");
ScanGameData();
Expand All @@ -88,7 +92,7 @@ private void SetupCkanDirectories()
if (!Directory.Exists(InstallHistoryDir()))
{
User.RaiseMessage("Creating {0}", InstallHistoryDir());
Directory.CreateDirectory(InstallHistoryDir());
txFileMgr.CreateDirectory(InstallHistoryDir());
}

// Clear any temporary files we find. If the directory
Expand Down
Loading

0 comments on commit c07d880

Please sign in to comment.