Skip to content

Commit

Permalink
Merge pull request #292 from pjf/291_moduleinstaller_fixes
Browse files Browse the repository at this point in the history
Bugfix: Make top-level components installable.
  • Loading branch information
techman83 committed Nov 9, 2014
2 parents 215025e + 5c7b501 commit 526ee0b
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 19 deletions.
10 changes: 9 additions & 1 deletion CKAN/CKAN/KSPPathUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,20 @@ public static string GetLastPathElement(string path)

/// <summary>
/// Gets the leading path elements. Ex: /a/b/c returns /a/b
///
/// Returns empty string if there is no leading path. (Eg: "Example.dll" -> "");
/// </summary>
/// <returns>The leading path elements.</returns>
/// <param name="path">The path to process.</param>
public static string GetLeadingPathElements(string path)
{
return Regex.Replace(NormalizePath(path), @"(^.*)/.+", "$1");
path = NormalizePath(path);

if (Regex.IsMatch(path, "/"))
{
return Regex.Replace(path, @"(^.*)/.+", "$1");
}
return String.Empty;
}
}
}
Expand Down
28 changes: 19 additions & 9 deletions CKAN/CKAN/ModuleInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -629,18 +629,28 @@ internal static List<InstallableFile> FindInstallableFiles(ModuleInstallDescript
internal static string TransformOutputName(string file, string outputName, string installDir)
{
string leadingPathToRemove = KSPPathUtils.GetLeadingPathElements(file);
string leadingRegEx = "^" + Regex.Escape(leadingPathToRemove) + "/";
if (!Regex.IsMatch(outputName, leadingRegEx))

// If there's a leading path to remove, then we have some extra work that
// needs doing...
if (leadingPathToRemove != string.Empty)
{
throw new BadMetadataKraken(null, "output file name not matching leading path of stanza.file");
string leadingRegEx = "^" + Regex.Escape(leadingPathToRemove) + "/";
if (!Regex.IsMatch(outputName, leadingRegEx))
{
throw new BadMetadataKraken(null,
String.Format("Output file name ({0}) not matching leading path of stanza.file ({1})",
outputName, leadingRegEx
)
);
}
// Strip off leading path name
outputName = Regex.Replace(outputName, leadingRegEx, "");
}
// Strip off leading path name
outputName = Regex.Replace(outputName, leadingRegEx, "");
string full_path = Path.Combine(installDir, outputName);
// Make the path pretty, and of course the prettiest paths use Unix separators. ;)
full_path = KSPPathUtils.NormalizePath(full_path);

return full_path;
// Return our snipped, normalised, and ready to go output filename!
return KSPPathUtils.NormalizePath(
Path.Combine(installDir, outputName)
);
}

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions CKAN/Tests/CKAN/KSPPathUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public void GetLeadingPathElements()
Assert.AreEqual("/a/b", CKAN.KSPPathUtils.GetLeadingPathElements("\\a/b\\c"), "With mixed slashes");
Assert.AreEqual("a/b", CKAN.KSPPathUtils.GetLeadingPathElements("a/b\\c"), "No starting slash");
Assert.AreEqual("/a/b", CKAN.KSPPathUtils.GetLeadingPathElements("\\a/b\\c\\"), "Trailing slash");

Assert.IsEmpty(CKAN.KSPPathUtils.GetLeadingPathElements("ModuleManager.2.5.1.dll"));
}

}
Expand Down
28 changes: 19 additions & 9 deletions CKAN/Tests/CKAN/ModuleInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public class ModuleInstaller
private static readonly string dogezip = Tests.TestData.DogeCoinFlagZip();
private static readonly CkanModule dogemod = Tests.TestData.DogeCoinFlag_101_module();

private static readonly string mm_zip = Tests.TestData.ModuleManagerZip();
private static readonly CkanModule mm_mod = Tests.TestData.ModuleManagerModule();

[Test()]
public void GenerateDefaultInstall()
{
Expand Down Expand Up @@ -83,14 +86,9 @@ public void FindInstallableFiles()
[Test()]
public void FindInstallableFilesWithKSP()
{
// TODO: Have our set-up in some sort of IDisposable object everything can use.
string ksp_dir = Tests.TestData.NewTempDir();
Tests.TestData.CopyDirectory(Tests.TestData.good_ksp_dir(), ksp_dir);
CKAN.KSP ksp = new CKAN.KSP(ksp_dir);

try
using (var tidy = new Tests.DisposableKSP())
{
List<InstallableFile> contents = CKAN.ModuleInstaller.FindInstallableFiles(dogemod, dogezip, ksp);
List<InstallableFile> contents = CKAN.ModuleInstaller.FindInstallableFiles(dogemod, dogezip, tidy.KSP);

// See if we can find an expected estination path in the right place.
string file = contents
Expand All @@ -100,9 +98,21 @@ public void FindInstallableFilesWithKSP()

Assert.IsNotNull(file);
}
finally
}

[Test]
public void ModuleManagerInstall()
{
using (var tidy = new Tests.DisposableKSP())
{
Directory.Delete(ksp_dir, true);
List<InstallableFile> contents = CKAN.ModuleInstaller.FindInstallableFiles(mm_mod, mm_zip, tidy.KSP);

string file = contents
.Select(x => x.destination)
.Where(x => Regex.IsMatch(x, @"ModuleManager\.2\.5\.1\.dll$"))
.FirstOrDefault();

Assert.IsNotNull(file, "ModuleManager install");
}
}

Expand Down
42 changes: 42 additions & 0 deletions CKAN/Tests/DisposableKSP.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.IO;

namespace Tests
{
/// <summary>
/// A disposable KSP instance. Use the `.KSP` property to access, will
/// be automatically cleaned up on DisposableKSP falling out of using() scope.
/// </summary>
public class DisposableKSP :IDisposable
{
private readonly string good_ksp = Tests.TestData.good_ksp_dir();
private CKAN.KSP _ksp;
private string disposable_dir;

public CKAN.KSP KSP {
get
{
return _ksp;
}
}

/// <summary>
/// Creates a copy of the provided argument, or a known-good KSP install if passed null.
/// Use .KSP to access the KSP object itself.
/// </summary>
public DisposableKSP(string directory_to_clone = null)
{
directory_to_clone = directory_to_clone ?? good_ksp;
disposable_dir = Tests.TestData.NewTempDir();
Tests.TestData.CopyDirectory(directory_to_clone, disposable_dir);
_ksp = new CKAN.KSP(disposable_dir);
}

public void Dispose()
{
Directory.Delete(disposable_dir, true);
_ksp = null; // In case .Dispose() was called manually.
}
}
}

15 changes: 15 additions & 0 deletions CKAN/Tests/TestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ public static string DataDir()
return Path.Combine(current, "../../../../t/data");
}

public static string DataDir(string file)
{
return Path.Combine(DataDir(), file);
}

/// <summary>
/// Returns the full path to DogeCoinFlag-1.01.zip
/// </summary>
Expand Down Expand Up @@ -198,6 +203,16 @@ public static string KspAvcJson()
return File.ReadAllText(Path.Combine(DataDir(), "ksp-avc.version"));
}

public static CKAN.CkanModule ModuleManagerModule()
{
return CKAN.CkanModule.FromFile(DataDir("ModuleManager-2.5.1.ckan"));
}

public static string ModuleManagerZip()
{
return DataDir("ModuleManager-2.5.1.zip");
}

// Where's my mkdtemp? Instead we'll make a random file, delete it, and
// fill its place with a directory.
// Taken from https://stackoverflow.com/a/20445952
Expand Down
1 change: 1 addition & 0 deletions CKAN/Tests/Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
<Compile Include="CKAN\SanityChecker.cs" />
<Compile Include="NetKAN\AVC.cs" />
<Compile Include="CKAN\KSPPathUtils.cs" />
<Compile Include="DisposableKSP.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
Expand Down
18 changes: 18 additions & 0 deletions t/data/ModuleManager-2.5.1.ckan
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"spec_version" : 1,
"name" : "Module Manager",
"identifier" : "ModuleManager",
"abstract" : "Modify KSP configs without conflict",
"download" : "https://ksp.sarbian.com/jenkins/job/ModuleManager/lastSuccessfulBuild/artifact/ModuleManager-2.5.1.zip",
"license" : "CC-BY-SA",
"author" : [ "ialdabaoth", "Sarbian" ],
"version" : "2.5.1",
"release_status" : "stable",
"ksp_version" : "0.25",
"install" : [
{
"file" : "ModuleManager.2.5.1.dll",
"install_to" : "GameData"
}
]
}
Binary file added t/data/ModuleManager-2.5.1.zip
Binary file not shown.

0 comments on commit 526ee0b

Please sign in to comment.