Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ Thumbs.db
obj/
[Rr]elease*/
_ReSharper*/
*.ReSharper
*.ReSharper.user
[Tt]est[Rr]esult*
build/
*.pidb
*.userprefs
*.swp
%temp%
*.swp
44 changes: 44 additions & 0 deletions LibGit2Sharp.Tests/BranchFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public void CanCreateBranchFromAnotherBranch()
newBranch.ShouldNotBeNull();
newBranch.Name.ShouldEqual(name);
newBranch.CanonicalName.ShouldEqual("refs/heads/" + name);
newBranch.IsCurrentRepositoryHead.ShouldBeFalse();
newBranch.Tip.ShouldNotBeNull();
newBranch.Tip.Sha.ShouldEqual("4c062a6361ae6959e06292c1fa5e2822d9c96345");
repo.Branches.SingleOrDefault(p => p.Name == name).ShouldNotBeNull();
Expand All @@ -49,6 +50,48 @@ public void CanCreateBranchFromAnotherBranch()
}
}

[Test]
public void TwoBranchesPointingAtTheSameCommitAreNotBothCurrent()
{
using (var path = new TemporaryCloneOfTestRepo())
using (var repo = new Repository(path.RepositoryPath))
{
var master = repo.Branches["refs/heads/master"];

var newBranch = repo.Branches.Create("clone-of-master", master.Tip.Sha);
newBranch.IsCurrentRepositoryHead.ShouldBeFalse();
}
}

[Test]
public void OnlyOneBranchIsTheHead()
{
using (var repo = new Repository(Constants.TestRepoPath))
{
Branch head = null;

foreach (var branch in repo.Branches)
{
bool isHead = branch.IsCurrentRepositoryHead;

if (!isHead)
{
continue;
}

if (head == null)
{
head = branch;
continue;
}

Assert.Fail("Both '{0}' and '{1}' appear to be Head.", head.CanonicalName, branch.CanonicalName);
}

head.ShouldNotBeNull();
}
}

[Test]
public void CanListAllBranches()
{
Expand All @@ -73,6 +116,7 @@ public void CanLookupLocalBranch()
master.IsRemote.ShouldBeFalse();
master.Name.ShouldEqual("master");
master.CanonicalName.ShouldEqual("refs/heads/master");
master.IsCurrentRepositoryHead.ShouldBeTrue();
master.Tip.Sha.ShouldEqual("4c062a6361ae6959e06292c1fa5e2822d9c96345");
}
}
Expand Down
151 changes: 114 additions & 37 deletions LibGit2Sharp.Tests/ReferenceFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace LibGit2Sharp.Tests
[TestFixture]
public class ReferenceFixture
{
private readonly List<string> expectedRefs = new List<string> { "refs/heads/packed-test", "refs/heads/packed", "refs/heads/br2", "refs/heads/master", "refs/heads/test", "refs/tags/test", "refs/tags/e90810b", "refs/tags/lw" };
private readonly List<string> expectedRefs = new List<string> {"refs/heads/packed-test", "refs/heads/packed", "refs/heads/br2", "refs/heads/master", "refs/heads/test", "refs/tags/test", "refs/tags/e90810b", "refs/tags/lw"};

[Test]
public void CanCreateReferenceFromSha()
Expand Down Expand Up @@ -40,32 +40,13 @@ public void CanCreateReferenceFromSymbol()
newRef.ShouldNotBeNull();
newRef.CanonicalName.ShouldEqual(name);
newRef.Target.ShouldNotBeNull();
((DirectReference)newRef.Target).Target.Sha.ShouldEqual("4c062a6361ae6959e06292c1fa5e2822d9c96345");
((DirectReference) newRef.Target).Target.Sha.ShouldEqual("4c062a6361ae6959e06292c1fa5e2822d9c96345");
repo.Refs.SingleOrDefault(p => p.CanonicalName == name).ShouldNotBeNull();

repo.Refs.Delete(newRef.CanonicalName);
}
}

[Test]
public void DeleteWithNullNameThrows()
{
using (var repo = new Repository(Constants.TestRepoPath))
{
Assert.Throws<ArgumentNullException>(() => repo.Refs.Delete(null));
}
}

[Test]
public void DeleteWithEmptyNameThrows()
{
using (var repo = new Repository(Constants.TestRepoPath))
{
Assert.Throws<ArgumentException>(() => repo.Refs.Delete(string.Empty));
}
}


[Test]
public void CanListAllReferences()
{
Expand All @@ -90,7 +71,7 @@ public void CanResolveHeadByName()
head.CanonicalName.ShouldEqual("HEAD");
head.Target.ShouldNotBeNull();
head.Target.CanonicalName.ShouldEqual("refs/heads/master");
((DirectReference)head.Target).Target.Sha.ShouldEqual("4c062a6361ae6959e06292c1fa5e2822d9c96345");
((DirectReference) head.Target).Target.Sha.ShouldEqual("4c062a6361ae6959e06292c1fa5e2822d9c96345");
Assert.IsInstanceOf<Commit>(((DirectReference) head.Target).Target);

var head2 = (SymbolicReference) repo.Refs.Head;
Expand All @@ -103,30 +84,30 @@ public void CanResolveHeadByName()
}

[Test]
public void CanResolveReferenceToAnAnnotatedTag()
public void CanResolveReferenceToALightweightTag()
{
using (var repo = new Repository(Constants.TestRepoPath))
{
var annTag = (DirectReference)repo.Refs["refs/tags/test"];
annTag.ShouldNotBeNull();
annTag.CanonicalName.ShouldEqual("refs/tags/test");
annTag.Target.ShouldNotBeNull();
annTag.Target.Sha.ShouldEqual("b25fa35b38051e4ae45d4222e795f9df2e43f1d1");
Assert.IsInstanceOf<TagAnnotation>(annTag.Target);
var lwTag = (DirectReference) repo.Refs["refs/tags/lw"];
lwTag.ShouldNotBeNull();
lwTag.CanonicalName.ShouldEqual("refs/tags/lw");
lwTag.Target.ShouldNotBeNull();
lwTag.Target.Sha.ShouldEqual("e90810b8df3e80c413d903f631643c716887138d");
Assert.IsInstanceOf<Commit>(lwTag.Target);
}
}

[Test]
public void CanResolveReferenceToALightweightTag()
public void CanResolveReferenceToAnAnnotatedTag()
{
using (var repo = new Repository(Constants.TestRepoPath))
{
var lwTag = (DirectReference)repo.Refs["refs/tags/lw"];
lwTag.ShouldNotBeNull();
lwTag.CanonicalName.ShouldEqual("refs/tags/lw");
lwTag.Target.ShouldNotBeNull();
lwTag.Target.Sha.ShouldEqual("e90810b8df3e80c413d903f631643c716887138d");
Assert.IsInstanceOf<Commit>(lwTag.Target);
var annTag = (DirectReference) repo.Refs["refs/tags/test"];
annTag.ShouldNotBeNull();
annTag.CanonicalName.ShouldEqual("refs/tags/test");
annTag.Target.ShouldNotBeNull();
annTag.Target.Sha.ShouldEqual("b25fa35b38051e4ae45d4222e795f9df2e43f1d1");
Assert.IsInstanceOf<TagAnnotation>(annTag.Target);
}
}

Expand All @@ -144,6 +125,43 @@ public void CanResolveRefsByName()
}
}

[Test]
public void CanUpdateTargetOnReference()
{
const string masterRef = "refs/heads/master";
using (var path = new TemporaryCloneOfTestRepo())
using (var repo = new Repository(path.RepositoryPath))
{
var sha = repo.Refs["refs/heads/test"].ResolveToDirectReference().Target.Sha;
var master = repo.Refs[masterRef];
master.ResolveToDirectReference().Target.Sha.ShouldNotEqual(sha);

repo.Refs.UpdateTarget(masterRef, sha);

master = repo.Refs[masterRef];
master.ResolveToDirectReference().Target.Sha.ShouldEqual(sha);
}
}

[Test]
public void CanUpdateTargetOnSymolicReference()
{
const string name = "refs/heads/unit_test";
using (var path = new TemporaryCloneOfTestRepo())
using (var repo = new Repository(path.RepositoryPath))
{
var newRef = (SymbolicReference) repo.Refs.Create(name, "refs/heads/master");
newRef.ShouldNotBeNull();

repo.Refs.UpdateTarget(newRef.CanonicalName, "refs/heads/test");

newRef = (SymbolicReference) repo.Refs[newRef.CanonicalName];
newRef.ResolveToDirectReference().Target.ShouldEqual(repo.Refs["refs/heads/test"].ResolveToDirectReference().Target);

repo.Refs.Delete(newRef.CanonicalName);
}
}

[Test]
public void CreateWithEmptyStringForTargetThrows()
{
Expand All @@ -170,7 +188,7 @@ public void CreateWithNullForTargetThrows()
using (var path = new TemporaryCloneOfTestRepo())
using (var repo = new Repository(path.RepositoryPath))
{
Assert.Throws<ArgumentNullException>(() => repo.Refs.Create("refs/heads/newref", (string)null));
Assert.Throws<ArgumentNullException>(() => repo.Refs.Create("refs/heads/newref", (string) null));
}
}

Expand All @@ -184,6 +202,24 @@ public void CreateWithNullStringThrows()
}
}

[Test]
public void DeleteWithEmptyNameThrows()
{
using (var repo = new Repository(Constants.TestRepoPath))
{
Assert.Throws<ArgumentException>(() => repo.Refs.Delete(string.Empty));
}
}

[Test]
public void DeleteWithNullNameThrows()
{
using (var repo = new Repository(Constants.TestRepoPath))
{
Assert.Throws<ArgumentNullException>(() => repo.Refs.Delete(null));
}
}

[Test]
public void ResolvingWithEmptyStringThrows()
{
Expand All @@ -201,5 +237,46 @@ public void ResolvingWithNullThrows()
Assert.Throws<ArgumentNullException>(() => { var head = repo.Refs[null]; });
}
}

[Test]
public void TryingToUpdateADirectRefWithSymbolFails()
{
const string name = "refs/heads/unit_test";
using (var path = new TemporaryCloneOfTestRepo())
using (var repo = new Repository(path.RepositoryPath))
{
var newRef = (SymbolicReference) repo.Refs.Create(name, "refs/heads/master");
newRef.ShouldNotBeNull();

Assert.Throws<ArgumentException>(
() => repo.Refs.UpdateTarget(newRef.CanonicalName, repo.Refs["refs/heads/test"].ResolveToDirectReference().Target.Sha));

repo.Refs.Delete(newRef.CanonicalName);
}
}

[Test]
public void TryingToUpdateASymbolicRefWithOidFails()
{
const string masterRef = "refs/heads/master";
using (var path = new TemporaryCloneOfTestRepo())
using (var repo = new Repository(path.RepositoryPath))
{
Assert.Throws<ArgumentException>(() => repo.Refs.UpdateTarget(masterRef, "refs/heads/test"));
}
}

[Test]
public void UpdateReferenceTargetWithBadParametersFails()
{
using (var path = new TemporaryCloneOfTestRepo())
using (var repo = new Repository(path.RepositoryPath))
{
Assert.Throws<ArgumentException>(() => repo.Refs.UpdateTarget(string.Empty, "refs/heads/packed"));
Assert.Throws<ArgumentException>(() => repo.Refs.UpdateTarget("master", string.Empty));
Assert.Throws<ArgumentNullException>(() => repo.Refs.UpdateTarget(null, "refs/heads/packed"));
Assert.Throws<ArgumentNullException>(() => repo.Refs.UpdateTarget("master", null));
}
}
}
}
4 changes: 2 additions & 2 deletions LibGit2Sharp/Branch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ internal Branch(string canonicalName, Commit tip, Repository repo)
/// <value>
/// <c>true</c> if this instance is current branch; otherwise, <c>false</c>.
/// </value>
public bool IsCurrentBranch
public bool IsCurrentRepositoryHead
{
get { return CanonicalName == repo.Refs.Head.ResolveToDirectReference().CanonicalName; }
get { return repo.Refs[CanonicalName] == repo.Refs.Head.ResolveToDirectReference(); }
}

/// <summary>
Expand Down
35 changes: 19 additions & 16 deletions LibGit2Sharp/Core/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ internal class NativeMethods
{
private const string libgit2 = "git2.dll";

[DllImport(libgit2, SetLastError = true)]
public static extern IntPtr git_blob_rawcontent(IntPtr blob);

[DllImport(libgit2, SetLastError = true)]
public static extern int git_blob_rawsize(IntPtr blob);

[DllImport(libgit2, SetLastError = true)]
public static extern IntPtr git_commit_author(IntPtr commit);

Expand Down Expand Up @@ -85,6 +91,12 @@ internal class NativeMethods
[DllImport(libgit2)]
public static extern int git_reference_resolve(out IntPtr resolvedReference, IntPtr reference);

[DllImport(libgit2, SetLastError = true)]
public static extern int git_reference_set_oid(IntPtr reference, ref GitOid id);

[DllImport(libgit2, SetLastError = true)]
public static extern int git_reference_set_target(IntPtr reference, string target);

[DllImport(libgit2)]
[return: MarshalAs(UnmanagedType.AnsiBStr)]
public static extern string git_reference_target(IntPtr reference);
Expand All @@ -107,7 +119,7 @@ internal class NativeMethods
[DllImport(libgit2)]
[return: MarshalAs(UnmanagedType.AnsiBStr)]
public static extern string git_repository_path(RepositorySafeHandle repository);

[DllImport(libgit2)]
[return: MarshalAs(UnmanagedType.AnsiBStr)]
public static extern string git_repository_workdir(RepositorySafeHandle repository);
Expand Down Expand Up @@ -152,36 +164,27 @@ internal class NativeMethods

[DllImport(libgit2, SetLastError = true)]
public static extern IntPtr git_tag_target_oid(IntPtr tag);

/* Blob */
[DllImport(libgit2, SetLastError = true)]
public static extern int git_blob_rawsize(IntPtr blob);

[DllImport(libgit2, SetLastError = true)]
public static extern IntPtr git_blob_rawcontent(IntPtr blob);

/* Tree */
public static extern int git_tree_entry_2object(out IntPtr obj, RepositorySafeHandle repo, IntPtr entry);

[DllImport(libgit2, SetLastError = true)]
[return: MarshalAs(UnmanagedType.AnsiBStr)]
public static extern string git_tree_entry_name(IntPtr entry);

public static extern int git_tree_entry_attributes(IntPtr entry);

[DllImport(libgit2, SetLastError = true)]
public static extern IntPtr git_tree_entry_byindex(IntPtr tree, int idx);

[DllImport(libgit2, SetLastError = true)]
public static extern IntPtr git_tree_entry_byname(IntPtr tree, string filename);

[DllImport(libgit2, SetLastError = true)]
public static extern int git_tree_entrycount(IntPtr tree);

[DllImport(libgit2, SetLastError = true)]
public static extern IntPtr git_tree_entry_id(IntPtr tree);

[DllImport(libgit2, SetLastError = true)]
public static extern int git_tree_entry_2object(out IntPtr obj, RepositorySafeHandle repo, IntPtr entry);
[return: MarshalAs(UnmanagedType.AnsiBStr)]
public static extern string git_tree_entry_name(IntPtr entry);

[DllImport(libgit2, SetLastError = true)]
public static extern int git_tree_entry_attributes(IntPtr entry);
public static extern int git_tree_entrycount(IntPtr tree);
}
}
Loading