Skip to content

Commit 9b0dc9c

Browse files
committed
#128 spike
1 parent 65c9b1c commit 9b0dc9c

File tree

7 files changed

+204
-0
lines changed

7 files changed

+204
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using LibGit2Sharp.Interactive;
2+
using LibGit2Sharp.Tests.TestHelpers;
3+
using Xunit;
4+
using Xunit.Extensions;
5+
6+
namespace LibGit2Sharp.Tests
7+
{
8+
public class InteractiveFixture : BaseFixture
9+
{
10+
[Theory]
11+
[InlineData(true)]
12+
[InlineData(false)]
13+
public void InteractiveStateHasExpectedValuesForNewRepo(bool isBare)
14+
{
15+
SelfCleaningDirectory scd = BuildSelfCleaningDirectory();
16+
using (var repo = Repository.Init(scd.DirectoryPath, isBare))
17+
{
18+
var state = repo.InteractiveState;
19+
Assert.Equal("master", state.HeadName);
20+
Assert.Equal(Operation.None, state.PendingOperation);
21+
}
22+
}
23+
24+
[Fact]
25+
public void InteractiveStateHasExpectedValuesForABareRepo()
26+
{
27+
using (var repo = new Repository(BareTestRepoPath))
28+
{
29+
var state = repo.InteractiveState;
30+
Assert.Equal("master", state.HeadName);
31+
Assert.Equal(Operation.None, state.PendingOperation);
32+
}
33+
}
34+
35+
[Fact]
36+
public void InteractiveStateHasExpectedValuesForStandardRepo()
37+
{
38+
var path = BuildTemporaryCloneOfTestRepo(StandardTestRepoPath);
39+
using (var repo = new Repository(path.RepositoryPath))
40+
{
41+
var state = repo.InteractiveState;
42+
Assert.Equal("master", state.HeadName);
43+
Assert.Equal(Operation.None, state.PendingOperation);
44+
45+
repo.Checkout("track-local");
46+
Assert.Equal("track-local", state.HeadName);
47+
}
48+
}
49+
50+
[Fact]
51+
public void InteractiveStateHasExpectedValuesForDetachedHead()
52+
{
53+
var path = BuildTemporaryCloneOfTestRepo(StandardTestRepoPath);
54+
using (var repo = new Repository(path.RepositoryPath))
55+
{
56+
repo.Checkout(repo.Head.Tip.Sha);
57+
58+
var state = repo.InteractiveState;
59+
Assert.Equal("(32eab9c...)", state.HeadName);
60+
Assert.Equal(Operation.None, state.PendingOperation);
61+
}
62+
}
63+
64+
[Fact]
65+
public void InteractiveStateHasExpectedValuesForInteractiveRebase()
66+
{
67+
var path = BuildTemporaryCloneOfTestRepo(StandardTestRepoPath);
68+
path.Touch("rebase-merge", "interactive");
69+
path.Touch("rebase-merge", "head-name", "refs/heads/master");
70+
71+
using (var repo = new Repository(path.RepositoryPath))
72+
{
73+
repo.Checkout(repo.Head.Tip.Sha);
74+
75+
var state = repo.InteractiveState;
76+
Assert.Equal("master", state.HeadName);
77+
Assert.Equal(Operation.RebaseInteractive, state.PendingOperation);
78+
}
79+
}
80+
}
81+
}

LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
<Compile Include="NoteFixture.cs" />
6060
<Compile Include="DiffBlobToBlobFixture.cs" />
6161
<Compile Include="DiffTreeToTargetFixture.cs" />
62+
<Compile Include="InteractiveFixture.cs" />
6263
<Compile Include="ObjectDatabaseFixture.cs" />
6364
<Compile Include="DiffTreeToTreeFixture.cs" />
6465
<Compile Include="RepositoryOptionsFixture.cs" />

LibGit2Sharp.Tests/TestHelpers/TemporaryCloneOfTestRepo.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.IO;
2+
using System.Text;
23

34
namespace LibGit2Sharp.Tests.TestHelpers
45
{
@@ -31,5 +32,13 @@ public TemporaryCloneOfTestRepo(IPostTestDirectoryRemover directoryRemover, stri
3132
}
3233

3334
public string RepositoryPath { get; private set; }
35+
36+
public void Touch(string parent, string file, string content = null)
37+
{
38+
var parentPath = Path.Combine(RepositoryPath, parent);
39+
Directory.CreateDirectory(parentPath);
40+
var filePath = Path.Combine(parentPath, file);
41+
File.WriteAllText(filePath, content ?? "", Encoding.ASCII);
42+
}
3443
}
3544
}

LibGit2Sharp/Interactive/Operation.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace LibGit2Sharp.Interactive
2+
{
3+
public enum Operation
4+
{
5+
None = 0,
6+
RebaseInteractive = 1,
7+
RebaseMerge = 2,
8+
Rebase = 3,
9+
ApplyMailbox = 4,
10+
ApplyMailboxOrRebase = 5,
11+
Merge = 6,
12+
CherryPick = 7,
13+
Bisect = 8,
14+
}
15+
}

LibGit2Sharp/Interactive/State.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System.IO;
2+
3+
namespace LibGit2Sharp.Interactive
4+
{
5+
/// <summary>
6+
/// Provides information about the repository's interactive state.
7+
/// </summary>
8+
public class State
9+
{
10+
private readonly Repository repo;
11+
private readonly string path;
12+
13+
internal State(Repository repo)
14+
{
15+
this.repo = repo;
16+
path = repo.Info.Path;
17+
}
18+
19+
/// <summary>
20+
/// The name of HEAD when the pending operation began, or the current HEAD.
21+
/// </summary>
22+
public string HeadName
23+
{
24+
get
25+
{
26+
if (!repo.Info.IsHeadDetached)
27+
return repo.Head.Name;
28+
29+
if (Exists("rebase-merge/head-name"))
30+
return File.ReadAllText(Path.Combine(path, "rebase-merge/head-name")).Replace("refs/heads/", "");
31+
32+
var tip = repo.Head.Tip;
33+
var detachedName = tip == null ? "unknown" : tip.Sha.Substring(0, 7) + "...";
34+
return "(" + detachedName + ")";
35+
}
36+
}
37+
38+
/// <summary>
39+
/// The pending interactive operation.
40+
/// </summary>
41+
public Operation PendingOperation
42+
{
43+
get
44+
{
45+
if (!repo.Info.IsHeadDetached)
46+
return Operation.None;
47+
48+
if (DirectoryExists("rebase-merge"))
49+
if (Exists("rebase-merge/interactive"))
50+
return Operation.RebaseInteractive;
51+
else
52+
return Operation.Merge;
53+
54+
if (DirectoryExists("rebase-apply"))
55+
if (Exists("rebase-apply/rebasing"))
56+
return Operation.Rebase;
57+
else if (Exists("rebase-apply/applying"))
58+
return Operation.ApplyMailbox;
59+
else
60+
return Operation.ApplyMailboxOrRebase;
61+
62+
if (Exists("MERGE_HEAD"))
63+
return Operation.Merge;
64+
65+
if (Exists("CHERRY_PICK_HEAD"))
66+
return Operation.CherryPick;
67+
68+
if (Exists("BISECT_LOG"))
69+
return Operation.Bisect;
70+
71+
return Operation.None;
72+
}
73+
}
74+
75+
private bool DirectoryExists(string relativePath)
76+
{
77+
return Directory.Exists(Path.Combine(path, relativePath));
78+
}
79+
80+
private bool Exists(string relativePath)
81+
{
82+
return File.Exists(Path.Combine(path, relativePath));
83+
}
84+
}
85+
}

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@
9898
<Compile Include="TreeChanges.cs" />
9999
<Compile Include="TreeEntryChanges.cs" />
100100
<Compile Include="LibGit2SharpException.cs" />
101+
<Compile Include="Interactive\Operation.cs" />
102+
<Compile Include="Interactive\State.cs" />
101103
<Compile Include="Core\Handles\ConfigurationSafeHandle.cs" />
102104
<Compile Include="Core\Ensure.cs" />
103105
<Compile Include="Core\Epoch.cs" />

LibGit2Sharp/Repository.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using LibGit2Sharp.Core;
77
using LibGit2Sharp.Core.Compat;
88
using LibGit2Sharp.Core.Handles;
9+
using LibGit2Sharp.Interactive;
910

1011
namespace LibGit2Sharp
1112
{
@@ -23,6 +24,7 @@ public class Repository : IDisposable
2324
private readonly Lazy<RemoteCollection> remotes;
2425
private readonly TagCollection tags;
2526
private readonly Lazy<RepositoryInformation> info;
27+
private readonly Lazy<State> interactiveState;
2628
private readonly Diff diff;
2729
private readonly NoteCollection notes;
2830
private readonly Lazy<ObjectDatabase> odb;
@@ -90,6 +92,7 @@ public Repository(string path, RepositoryOptions options = null)
9092
branches = new BranchCollection(this);
9193
tags = new TagCollection(this);
9294
info = new Lazy<RepositoryInformation>(() => new RepositoryInformation(this, isBare));
95+
interactiveState = new Lazy<State>(() => new State(this));
9396
config = new Lazy<Configuration>(() => RegisterForCleanup(new Configuration(this, configurationGlobalFilePath, configurationSystemFilePath)));
9497
remotes = new Lazy<RemoteCollection>(() => new RemoteCollection(this));
9598
odb = new Lazy<ObjectDatabase>(() => new ObjectDatabase(this));
@@ -213,6 +216,14 @@ public RepositoryInformation Info
213216
get { return info.Value; }
214217
}
215218

219+
/// <summary>
220+
/// Provides information about this repository's interactive state (merge, rebase, etc).
221+
/// </summary>
222+
public State InteractiveState
223+
{
224+
get { return interactiveState.Value; }
225+
}
226+
216227
/// <summary>
217228
/// Provides access to diffing functionalities to show changes between the working tree and the index or a tree, changes between the index and a tree, changes between two trees, or changes between two files on disk.
218229
/// </summary>

0 commit comments

Comments
 (0)