Skip to content
This repository was archived by the owner on Jun 27, 2019. It is now read-only.

Commit 403fd75

Browse files
Added extensions and fixtures for testing purposes
1 parent 25d0a38 commit 403fd75

File tree

8 files changed

+399
-1
lines changed

8 files changed

+399
-1
lines changed

src/GitTools.Core/Constants.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,30 @@
11
namespace GitTools
22
{
3-
// TODO: Constants go here
3+
using System;
4+
using LibGit2Sharp;
5+
6+
public static class TestValues
7+
{
8+
private static DateTimeOffset _simulatedTime = DateTimeOffset.Now.AddHours(-1);
9+
10+
public static DateTimeOffset Now
11+
{
12+
get
13+
{
14+
_simulatedTime = _simulatedTime.AddMinutes(1);
15+
return _simulatedTime;
16+
}
17+
}
18+
19+
public static Signature SignatureNow()
20+
{
21+
var dateTimeOffset = Now;
22+
return Signature(dateTimeOffset);
23+
}
24+
25+
public static Signature Signature(DateTimeOffset dateTimeOffset)
26+
{
27+
return new Signature("A. U. Thor", "[email protected]", dateTimeOffset);
28+
}
29+
}
430
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace GitTools
2+
{
3+
using System.Text;
4+
5+
public static class StringBuilderExtensions
6+
{
7+
//[StringFormatMethod("format")]
8+
public static void AppendLineFormat(this StringBuilder stringBuilder, string format, params object[] args)
9+
{
10+
stringBuilder.AppendFormat(format, args);
11+
stringBuilder.AppendLine();
12+
}
13+
}
14+
}

src/GitTools.Core/GitTools.Core.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,23 @@
6868
<Compile Include="Exceptions\GitToolsException.cs" />
6969
<Compile Include="Extensions\IntExtensions.cs" />
7070
<Compile Include="Extensions\LibGitExtensions.cs" />
71+
<Compile Include="Extensions\StringBuilderExtensions.cs" />
7172
<Compile Include="Extensions\StringExtensions.cs" />
7273
<Compile Include="Git\GitDirFinder.cs" />
7374
<Compile Include="Git\GitPreparer.cs" />
7475
<Compile Include="Git\Interfaces\IRepositoryPreparer.cs" />
7576
<Compile Include="Git\RepositoryLoader.cs" />
7677
<Compile Include="Helpers\DeleteHelper.cs" />
7778
<Compile Include="Helpers\GitHelper.cs" />
79+
<Compile Include="Helpers\ProcessHelper.cs" />
7880
<Compile Include="IO\TemporaryFilesContext.cs" />
7981
<Compile Include="Logging\Extensions\LogExtensions.cs" />
8082
<Compile Include="ModuleInitializer.cs" />
8183
<Compile Include="Properties\AssemblyInfo.cs" />
84+
<Compile Include="Testing\Extensions\GitTestExtensions.cs" />
85+
<Compile Include="Testing\Fixtures\EmptyRepositoryFixture.cs" />
86+
<Compile Include="Testing\Fixtures\RemoteRepositoryFixture.cs" />
87+
<Compile Include="Testing\Fixtures\RepositoryFixtureBase.cs" />
8288
</ItemGroup>
8389
<ItemGroup>
8490
<EmbeddedResource Include="..\..\lib\LibGit2Sharp.0.21.0.176\lib\net40\NativeBinaries\amd64\git2-e0902fb.dll">
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
namespace GitTools
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Diagnostics;
6+
using System.IO;
7+
using System.Runtime.InteropServices;
8+
using System.Threading;
9+
10+
public static class ProcessHelper
11+
{
12+
private static volatile object _lockObject = new object();
13+
14+
// http://social.msdn.microsoft.com/Forums/en/netfxbcl/thread/f6069441-4ab1-4299-ad6a-b8bb9ed36be3
15+
public static Process Start(ProcessStartInfo startInfo)
16+
{
17+
Process process;
18+
19+
lock (_lockObject)
20+
{
21+
using (new ChangeErrorMode(ErrorModes.FailCriticalErrors | ErrorModes.NoGpFaultErrorBox))
22+
{
23+
process = Process.Start(startInfo);
24+
process.PriorityClass = ProcessPriorityClass.Idle;
25+
}
26+
}
27+
28+
return process;
29+
}
30+
31+
// http://csharptest.net/532/using-processstart-to-capture-console-output/
32+
public static int Run(Action<string> output, Action<string> errorOutput, TextReader input, string exe, string args, string workingDirectory, params KeyValuePair<string, string>[] environmentalVariables)
33+
{
34+
if (String.IsNullOrEmpty(exe))
35+
{
36+
throw new FileNotFoundException();
37+
}
38+
39+
if (output == null)
40+
{
41+
throw new ArgumentNullException("output");
42+
}
43+
44+
var psi = new ProcessStartInfo
45+
{
46+
UseShellExecute = false,
47+
RedirectStandardError = true,
48+
RedirectStandardOutput = true,
49+
RedirectStandardInput = true,
50+
WindowStyle = ProcessWindowStyle.Hidden,
51+
CreateNoWindow = true,
52+
ErrorDialog = false,
53+
WorkingDirectory = workingDirectory ?? Environment.CurrentDirectory,
54+
FileName = exe,
55+
Arguments = args
56+
};
57+
58+
foreach (var environmentalVariable in environmentalVariables)
59+
{
60+
if (!psi.EnvironmentVariables.ContainsKey(environmentalVariable.Key) && environmentalVariable.Value != null)
61+
psi.EnvironmentVariables.Add(environmentalVariable.Key, environmentalVariable.Value);
62+
if (psi.EnvironmentVariables.ContainsKey(environmentalVariable.Key) && environmentalVariable.Value == null)
63+
psi.EnvironmentVariables.Remove(environmentalVariable.Key);
64+
}
65+
66+
using (var process = Process.Start(psi))
67+
{
68+
using (var mreOut = new ManualResetEvent(false))
69+
{
70+
using (var mreErr = new ManualResetEvent(false))
71+
{
72+
process.EnableRaisingEvents = true;
73+
process.OutputDataReceived += (o, e) =>
74+
{
75+
// ReSharper disable once AccessToDisposedClosure
76+
if (e.Data == null)
77+
{
78+
mreOut.Set();
79+
}
80+
else
81+
{
82+
output(e.Data);
83+
}
84+
};
85+
process.BeginOutputReadLine();
86+
process.ErrorDataReceived += (o, e) =>
87+
{
88+
// ReSharper disable once AccessToDisposedClosure
89+
if (e.Data == null)
90+
{
91+
mreErr.Set();
92+
}
93+
else
94+
{
95+
errorOutput(e.Data);
96+
}
97+
};
98+
99+
process.BeginErrorReadLine();
100+
101+
string line;
102+
while (input != null && null != (line = input.ReadLine()))
103+
{
104+
process.StandardInput.WriteLine(line);
105+
}
106+
107+
process.StandardInput.Close();
108+
process.WaitForExit();
109+
110+
mreOut.WaitOne();
111+
mreErr.WaitOne();
112+
113+
return process.ExitCode;
114+
}
115+
}
116+
}
117+
}
118+
119+
[Flags]
120+
public enum ErrorModes
121+
{
122+
Default = 0x0,
123+
FailCriticalErrors = 0x1,
124+
NoGpFaultErrorBox = 0x2,
125+
NoAlignmentFaultExcept = 0x4,
126+
NoOpenFileErrorBox = 0x8000
127+
}
128+
129+
public struct ChangeErrorMode : IDisposable
130+
{
131+
private readonly int _oldMode;
132+
133+
public ChangeErrorMode(ErrorModes mode)
134+
{
135+
_oldMode = SetErrorMode((int)mode);
136+
}
137+
138+
void IDisposable.Dispose() { SetErrorMode(_oldMode); }
139+
140+
[DllImport("kernel32.dll")]
141+
static extern int SetErrorMode(int newMode);
142+
}
143+
}
144+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
namespace GitTools.Testing
2+
{
3+
using System;
4+
using System.Diagnostics;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Text;
8+
using LibGit2Sharp;
9+
10+
public static class GitTestExtensions
11+
{
12+
private static int pad = 1;
13+
14+
public static void DumpGraph(this IRepository repository)
15+
{
16+
var output = new StringBuilder();
17+
18+
ProcessHelper.Run(
19+
o => output.AppendLine(o),
20+
e => output.AppendLineFormat("ERROR: {0}", e),
21+
null,
22+
"git",
23+
@"log --graph --abbrev-commit --decorate --date=relative --all",
24+
repository.Info.Path);
25+
26+
Trace.Write(output.ToString());
27+
}
28+
29+
public static Commit MakeACommit(this IRepository repository)
30+
{
31+
return CreateFileAndCommit(repository, Guid.NewGuid().ToString());
32+
}
33+
34+
public static void MergeNoFF(this IRepository repository, string branch)
35+
{
36+
MergeNoFF(repository, branch, TestValues.SignatureNow());
37+
}
38+
39+
public static void MergeNoFF(this IRepository repository, string branch, Signature sig)
40+
{
41+
// Fixes a race condition
42+
repository.Merge(repository.FindBranch(branch), sig, new MergeOptions
43+
{
44+
FastForwardStrategy = FastForwardStrategy.NoFastFoward
45+
});
46+
}
47+
48+
public static Commit[] MakeCommits(this IRepository repository, int numCommitsToMake)
49+
{
50+
return Enumerable.Range(1, numCommitsToMake)
51+
.Select(x => repository.MakeACommit())
52+
.ToArray();
53+
}
54+
55+
public static Commit CreateFileAndCommit(this IRepository repository, string relativeFileName)
56+
{
57+
var randomFile = Path.Combine(repository.Info.WorkingDirectory, relativeFileName);
58+
if (File.Exists(randomFile))
59+
{
60+
File.Delete(randomFile);
61+
}
62+
63+
var totalWidth = 36 + (pad++ % 10);
64+
var contents = Guid.NewGuid().ToString().PadRight(totalWidth, '.');
65+
File.WriteAllText(randomFile, contents);
66+
67+
repository.Stage(randomFile);
68+
69+
return repository.Commit(string.Format("Test Commit for file '{0}'", relativeFileName),
70+
TestValues.SignatureNow(), TestValues.SignatureNow());
71+
}
72+
73+
public static Tag MakeATaggedCommit(this IRepository repository, string tag)
74+
{
75+
var commit = repository.MakeACommit();
76+
var existingTag = repository.Tags.SingleOrDefault(t => t.Name == tag);
77+
if (existingTag != null)
78+
return existingTag;
79+
return repository.Tags.Add(tag, commit);
80+
}
81+
82+
public static Branch CreatePullRequest(this IRepository repository, string from, string to, int prNumber = 2, bool isRemotePr = true)
83+
{
84+
repository.Checkout(to);
85+
repository.MergeNoFF(from);
86+
var branch = repository.CreateBranch("pull/" + prNumber + "/merge");
87+
repository.Checkout(branch.Name);
88+
repository.Checkout(to);
89+
repository.Reset(ResetMode.Hard, "HEAD~1");
90+
var pullBranch = repository.Checkout("pull/" + prNumber + "/merge");
91+
if (isRemotePr)
92+
{
93+
// If we delete the branch, it is effectively the same as remote PR
94+
repository.Branches.Remove(from);
95+
}
96+
97+
return pullBranch;
98+
}
99+
}
100+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
namespace GitTools.Testing
2+
{
3+
using System;
4+
using LibGit2Sharp;
5+
6+
public class EmptyRepositoryFixture : RepositoryFixtureBase
7+
{
8+
public EmptyRepositoryFixture() :
9+
base(CreateNewRepository)
10+
{
11+
}
12+
13+
public void DumpGraph()
14+
{
15+
Repository.DumpGraph();
16+
}
17+
18+
private static IRepository CreateNewRepository(string path)
19+
{
20+
LibGit2Sharp.Repository.Init(path);
21+
Console.WriteLine("Created git repository at '{0}'", path);
22+
23+
return new Repository(path);
24+
}
25+
}
26+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
namespace GitTools.Testing
2+
{
3+
using System;
4+
using LibGit2Sharp;
5+
6+
public class RemoteRepositoryFixture : RepositoryFixtureBase
7+
{
8+
public IRepository LocalRepository;
9+
public string LocalRepositoryPath;
10+
11+
public RemoteRepositoryFixture()
12+
: base(CreateNewRepository)
13+
{
14+
CloneRepository();
15+
}
16+
17+
private static IRepository CreateNewRepository(string path)
18+
{
19+
LibGit2Sharp.Repository.Init(path);
20+
Console.WriteLine("Created git repository at '{0}'", path);
21+
22+
var repo = new Repository(path);
23+
repo.MakeCommits(5);
24+
return repo;
25+
}
26+
27+
private void CloneRepository()
28+
{
29+
LocalRepositoryPath = TemporaryFilesContext.GetDirectory("/");
30+
LibGit2Sharp.Repository.Clone(RepositoryPath, LocalRepositoryPath);
31+
LocalRepository = new Repository(LocalRepositoryPath);
32+
}
33+
34+
public override void Dispose()
35+
{
36+
LocalRepository.Dispose();
37+
38+
base.Dispose();
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)