Skip to content

Commit

Permalink
Cross platform support (Windows / Linux / OS X) by @krippz
Browse files Browse the repository at this point in the history
Merge pull request #11 from krippz/crossplat
  • Loading branch information
JohannesHoppe committed Jul 24, 2016
2 parents 9a986cb + abfbe3c commit ab355ce
Show file tree
Hide file tree
Showing 32 changed files with 5,774 additions and 1,896 deletions.
6 changes: 6 additions & 0 deletions src/Mongo2Go/Helper/FileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,11 @@ public void DeleteFile(string fullFileName)
File.Delete(fullFileName);
}
}

public void MakeFileExecutable (string path)
{
//when on linux or osx we must set the executeble flag on mongo binarys
File.SetAttributes (path, (FileAttributes)((int)File.GetAttributes (path) | 0x80000000));
}
}
}
10 changes: 5 additions & 5 deletions src/Mongo2Go/Helper/FolderSearch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static string FindFolder(this string startPath, string searchPattern)
{
string currentPath = startPath;

foreach (var part in searchPattern.Split(new[] { @"\" }, StringSplitOptions.None))
foreach (var part in searchPattern.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None))
{
string[] matchesDirectory = Directory.GetDirectories(currentPath, part);
if (!matchesDirectory.Any())
Expand Down Expand Up @@ -56,14 +56,14 @@ private static string FindFolderUpwards(this string startPath, string searchPatt

internal static string RemoveLastPart(this string path)
{
if (!path.Contains(@"\"))
if (!path.Contains(Path.DirectorySeparatorChar))
{
return null;
}

List<string> parts = path.Split(new[] {@"\"}, StringSplitOptions.None).ToList();
List<string> parts = path.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None).ToList();
parts.RemoveAt(parts.Count() - 1);
return string.Join(@"\", parts.ToArray());
return string.Join(Path.DirectorySeparatorChar.ToString(), parts.ToArray());
}

/// <summary>
Expand All @@ -79,7 +79,7 @@ public static string FinalizePath(string fileName)
}
else
{
finalPath = CurrentExecutingDirectory() + @"\" + fileName;
finalPath = Path.Combine (CurrentExecutingDirectory (), fileName);
finalPath = Path.GetFullPath(finalPath);
}

Expand Down
1 change: 1 addition & 0 deletions src/Mongo2Go/Helper/IFileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ public interface IFileSystem
void CreateFolder(string path);
void DeleteFolder(string path);
void DeleteFile(string fullFileName);
void MakeFileExecutable (string path );
}
}
7 changes: 7 additions & 0 deletions src/Mongo2Go/Helper/IMongoBinaryLocator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Mongo2Go.Helper
{
public interface IMongoBinaryLocator
{
string Directory { get; }
}
}
49 changes: 49 additions & 0 deletions src/Mongo2Go/Helper/MongoBinaryLocator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;
using System.IO;

namespace Mongo2Go.Helper
{

public class MongoBinaryLocator : IMongoBinaryLocator
{
private string nugetPrefix = System.IO.Path.Combine ("packages", "Mongo2Go*");
private string searchPattern = "";
private string binFolder = string.Empty;

public MongoBinaryLocator (string binSearchPattern)
{
if (string.IsNullOrEmpty (binSearchPattern)) {
throw new ArgumentException ("Missing the search pattern for finding the mongoDb binaries.", "binSearchPattern");
}

searchPattern = binSearchPattern;
}

public string Directory {
get {
if (string.IsNullOrEmpty (binFolder)){
return binFolder = ResolveBinariesDirectory ();
} else {
return binFolder;
}
}
}

private string ResolveBinariesDirectory ()
{
// 1st: path when installed via nuget
// 2nd: path when started from solution
string binariesFolder = FolderSearch.CurrentExecutingDirectory ().FindFolderUpwards (System.IO.Path.Combine (nugetPrefix, searchPattern)) ??
FolderSearch.CurrentExecutingDirectory ().FindFolderUpwards (searchPattern);

if (binariesFolder == null) {
throw new MonogDbBinariesNotFoundException (string.Format (
"Could not find Mongo binaries using {0}. We walk up the directories {1} levels from {2}",
searchPattern,
FolderSearch.MaxLevelOfRecursion,
FolderSearch.CurrentExecutingDirectory ()));
}
return binariesFolder;
}
}
}
2 changes: 1 addition & 1 deletion src/Mongo2Go/Helper/MongoDbProcessStarter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public IMongoDbProcess Start(string binariesDirectory, string dataDirectory, int
/// </summary>
public IMongoDbProcess Start(string binariesDirectory, string dataDirectory, int port, bool doNotKill)
{
string fileName = @"{0}\{1}".Formatted(binariesDirectory, MongoDbDefaults.MongodExecutable);
string fileName = @"{0}{1}{2}".Formatted(binariesDirectory, System.IO.Path.DirectorySeparatorChar.ToString(), MongoDbDefaults.MongodExecutable);
string arguments = @"--dbpath ""{0}"" --port {1} --nohttpinterface --nojournal".Formatted(dataDirectory, port);

WrappedProcess wrappedProcess = ProcessControl.ProcessFactory(fileName, arguments);
Expand Down
2 changes: 1 addition & 1 deletion src/Mongo2Go/Helper/PortPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public int GetNextOpenPort()
{
lock (_lock)
{
PortWatcher portWatcher = new PortWatcher();
IPortWatcher portWatcher = PortWatcherFactory.CreatePortWatcher();
int newAvailablePort = portWatcher.FindOpenPort(_startPort);

_startPort = newAvailablePort + 1;
Expand Down
29 changes: 29 additions & 0 deletions src/Mongo2Go/Helper/PortWatcherFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace Mongo2Go.Helper
{
public class PortWatcherFactory
{
public static IPortWatcher CreatePortWatcher()
{
IPortWatcher portwatcher = null;

switch (Environment.OSVersion.Platform)
{
case PlatformID.Unix:
portwatcher = new UnixPortWatcher ();
break;

default:
portwatcher = new PortWatcher ();
break;
}

return portwatcher;
}
}
}
47 changes: 47 additions & 0 deletions src/Mongo2Go/Helper/UnixPortWatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Net;
using System.Net.Sockets;

namespace Mongo2Go.Helper
{

public class UnixPortWatcher : IPortWatcher
{
public int FindOpenPort (int startPort)
{
int port = startPort;
do {
if (IsPortAvailable (port)) {
break;
}

if (port == MongoDbDefaults.TestStartPort + 100) {
throw new NoFreePortFoundException ();
}

++port;

} while (true);

return port;
}

public bool IsPortAvailable (int portNumber)
{
bool result = false;

TcpListener tcpListener = new TcpListener (IPAddress.Loopback, portNumber);
try {
tcpListener.Start ();
} catch (SocketException) {
result = false;

} finally
{
tcpListener.Stop ();
result = true;
}

return result;
}
}
}
4 changes: 4 additions & 0 deletions src/Mongo2Go/Mongo2Go.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
<Compile Include="State.cs">
<DependentUpon>MongoDbRunner.cs</DependentUpon>
</Compile>
<Compile Include="Helper\MongoBinaryLocator.cs" />
<Compile Include="Helper\IMongoBinaryLocator.cs" />
<Compile Include="Helper\UnixPortWatcher.cs" />
<Compile Include="Helper\PortWatcherFactory.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
71 changes: 33 additions & 38 deletions src/Mongo2Go/MongoDbRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ public partial class MongoDbRunner : IDisposable
private readonly IFileSystem _fileSystem;
private readonly string _dataDirectoryWithPort;
private readonly int _port;

private const string BinariesSearchPattern = @"packages\Mongo2Go*\tools\mongodb-win32*\bin";
private const string BinariesSearchPatternSolution = @"tools\mongodb-win32*\bin";
private readonly IMongoBinaryLocator _mongoBin;

/// <summary>
/// State of the current MongoDB instance
Expand All @@ -31,14 +29,14 @@ public partial class MongoDbRunner : IDisposable
/// On dispose: kills them and deletes their data directory
/// </summary>
/// <remarks>Should be used for integration tests</remarks>
public static MongoDbRunner Start(string dataDirectory = MongoDbDefaults.DataDirectory)
public static MongoDbRunner Start(string mongoBinSearchPattern = @"tools\mongodb-win32*\bin", string dataDirectory = MongoDbDefaults.DataDirectory)
{
return new MongoDbRunner(PortPool.GetInstance, new FileSystem(), new MongoDbProcessStarter(), dataDirectory);
return new MongoDbRunner(PortPool.GetInstance, new FileSystem(), new MongoDbProcessStarter(), new MongoBinaryLocator (mongoBinSearchPattern), dataDirectory);
}

internal static MongoDbRunner StartUnitTest(IPortPool portPool, IFileSystem fileSystem, IMongoDbProcessStarter processStarter)
internal static MongoDbRunner StartUnitTest(IPortPool portPool, IFileSystem fileSystem, IMongoDbProcessStarter processStarter, IMongoBinaryLocator mongoBin)
{
return new MongoDbRunner(portPool, fileSystem, processStarter, MongoDbDefaults.DataDirectory);
return new MongoDbRunner(portPool, fileSystem, processStarter, mongoBin, MongoDbDefaults.DataDirectory);
}

/// <summary>
Expand All @@ -48,39 +46,44 @@ internal static MongoDbRunner StartUnitTest(IPortPool portPool, IFileSystem file
/// Should be used for local debugging only
/// WARNING: one single instance on one single machine is not a suitable setup for productive environments!!!
/// </remarks>
public static MongoDbRunner StartForDebugging(string dataDirectory = MongoDbDefaults.DataDirectory)
public static MongoDbRunner StartForDebugging(string mongoBinSearchPattern = @"tools\mongodb-win32*\bin", string dataDirectory = MongoDbDefaults.DataDirectory)
{
return new MongoDbRunner(new ProcessWatcher(), new PortWatcher(), new FileSystem(), new MongoDbProcessStarter(), dataDirectory);
return new MongoDbRunner(new ProcessWatcher(), new PortWatcher(), new FileSystem(), new MongoDbProcessStarter(), new MongoBinaryLocator(mongoBinSearchPattern), dataDirectory);
}

internal static MongoDbRunner StartForDebuggingUnitTest(IProcessWatcher processWatcher, IPortWatcher portWatcher, IFileSystem fileSystem, IMongoDbProcessStarter processStarter)
internal static MongoDbRunner StartForDebuggingUnitTest(IProcessWatcher processWatcher, IPortWatcher portWatcher, IFileSystem fileSystem, IMongoDbProcessStarter processStarter, IMongoBinaryLocator mongoBin)
{
return new MongoDbRunner(processWatcher, portWatcher, fileSystem, processStarter, MongoDbDefaults.DataDirectory);
return new MongoDbRunner(processWatcher, portWatcher, fileSystem, processStarter,mongoBin, MongoDbDefaults.DataDirectory);
}

/// <summary>
/// Executes Mongoimport on the associated MongoDB Instace
/// </summary>
public void Import(string database, string collection, string inputFile, bool drop)
{
MongoImportExport.Import(BinariesDirectory, _port, database, collection, inputFile, drop);
{

MongoImportExport.Import(_mongoBin.Directory, _port, database, collection, inputFile, drop);
}

/// <summary>
/// Executes Mongoexport on the associated MongoDB Instace
/// </summary>
public void Export(string database, string collection, string outputFile)
{
MongoImportExport.Export(BinariesDirectory, _port, database, collection, outputFile);
{

MongoImportExport.Export(_mongoBin.Directory, _port, database, collection, outputFile);
}

/// <summary>
/// usage: local debugging
/// </summary>
private MongoDbRunner(IProcessWatcher processWatcher, IPortWatcher portWatcher, IFileSystem fileSystem, IMongoDbProcessStarter processStarter, string dataDirectory)
private MongoDbRunner(IProcessWatcher processWatcher, IPortWatcher portWatcher, IFileSystem fileSystem, IMongoDbProcessStarter processStarter,IMongoBinaryLocator mongoBin, string dataDirectory)
{
_fileSystem = fileSystem;
_port = MongoDbDefaults.DefaultPort;
_mongoBin = mongoBin;

MakeMongoBinarysExecutable();

ConnectionString = "mongodb://localhost:{0}/".Formatted(_port);

Expand All @@ -96,49 +99,41 @@ private MongoDbRunner(IProcessWatcher processWatcher, IPortWatcher portWatcher,
}

_fileSystem.CreateFolder(dataDirectory);
_fileSystem.DeleteFile(@"{0}\{1}".Formatted(dataDirectory, MongoDbDefaults.Lockfile));
_mongoDbProcess = processStarter.Start(BinariesDirectory, dataDirectory, _port, true);
_fileSystem.DeleteFile(@"{0}{1}{2}".Formatted(dataDirectory, System.IO.Path.DirectorySeparatorChar.ToString (), MongoDbDefaults.Lockfile));
_mongoDbProcess = processStarter.Start(_mongoBin.Directory, dataDirectory, _port, true);

State = State.Running;
}

/// <summary>
/// usage: integration tests
/// </summary>
private MongoDbRunner(IPortPool portPool, IFileSystem fileSystem, IMongoDbProcessStarter processStarter, string dataDirectory)
private MongoDbRunner(IPortPool portPool, IFileSystem fileSystem, IMongoDbProcessStarter processStarter, IMongoBinaryLocator mongoBin, string dataDirectory)
{
_fileSystem = fileSystem;
_port = portPool.GetNextOpenPort();
_mongoBin = mongoBin;

MakeMongoBinarysExecutable();

ConnectionString = "mongodb://localhost:{0}/".Formatted(_port);

_dataDirectoryWithPort = "{0}_{1}".Formatted(dataDirectory, _port);
_fileSystem.CreateFolder(_dataDirectoryWithPort);
_fileSystem.DeleteFile(@"{0}\{1}".Formatted(_dataDirectoryWithPort, MongoDbDefaults.Lockfile));
_mongoDbProcess = processStarter.Start(BinariesDirectory, _dataDirectoryWithPort, _port);
_fileSystem.DeleteFile(@"{0}{1}{2}".Formatted(_dataDirectoryWithPort, System.IO.Path.DirectorySeparatorChar.ToString(), MongoDbDefaults.Lockfile));

_mongoDbProcess = processStarter.Start(_mongoBin.Directory, _dataDirectoryWithPort, _port);

State = State.Running;
}

private static string BinariesDirectory
private void MakeMongoBinarysExecutable()
{
get
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
// 1st: path when installed via nuget
// 2nd: path when started from solution
string binariesFolder = FolderSearch.CurrentExecutingDirectory().FindFolderUpwards(BinariesSearchPattern) ??
FolderSearch.CurrentExecutingDirectory().FindFolderUpwards(BinariesSearchPatternSolution);

if (binariesFolder == null)
{
throw new MonogDbBinariesNotFoundException(string.Format(
"Could not find Mongo binaries using {0} or {1}. We walk up the directories {2} levels from {3}",
BinariesSearchPattern,
BinariesSearchPatternSolution,
FolderSearch.MaxLevelOfRecursion,
FolderSearch.CurrentExecutingDirectory()));
}
return binariesFolder;
_fileSystem.MakeFileExecutable (System.IO.Path.Combine (_mongoBin.Directory, MongoDbDefaults.MongodExecutable));
_fileSystem.MakeFileExecutable (System.IO.Path.Combine (_mongoBin.Directory, MongoDbDefaults.MongoExportExecutable));
_fileSystem.MakeFileExecutable (System.IO.Path.Combine (_mongoBin.Directory, MongoDbDefaults.MongoImportExecutable));
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/Mongo2GoTests/Mongo2GoTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@
<Name>Mongo2Go</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
Loading

0 comments on commit ab355ce

Please sign in to comment.