Skip to content

Commit

Permalink
Allow to query the commit history of an empty repository
Browse files Browse the repository at this point in the history
Fix issue #30.
  • Loading branch information
nulltoken committed May 24, 2011
1 parent da2a2c7 commit 3034aa9
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 27 deletions.
31 changes: 12 additions & 19 deletions LibGit2Sharp.Tests/CommitFixture.cs
Expand Up @@ -77,7 +77,7 @@ public void CanEnumerateCommitsFromSha()
}

[Test]
public void BuildingACommitCollectionFromUnknownShaOrInvalidReferenceThrows()
public void QueryingTheCommitHistoryWithUnknownShaOrInvalidReferenceThrows()
{
using (var repo = new Repository(Constants.TestRepoPath))
{
Expand All @@ -88,6 +88,17 @@ public void BuildingACommitCollectionFromUnknownShaOrInvalidReferenceThrows()
}
}

[Test]
public void QueryingTheCommitHistoryWithBadParamsThrows()
{
using (var repo = new Repository(Constants.TestRepoPath))
{
Assert.Throws<ArgumentException>(() => repo.Commits.QueryBy(new Filter { Since = string.Empty }));
Assert.Throws<ArgumentNullException>(() => repo.Commits.QueryBy(new Filter { Since = null }));
Assert.Throws<ArgumentNullException>(() => repo.Commits.QueryBy(null));
}
}

[Test]
public void CanEnumerateCommitsWithReverseTimeSorting()
{
Expand Down Expand Up @@ -208,23 +219,5 @@ public void CanReadCommitWithMultipleParents()
commit.Parents.Count().ShouldEqual(2);
}
}

[Test]
public void PushingEmptyShaThrows()
{
using (var repo = new Repository(Constants.TestRepoPath))
{
Assert.Throws<ArgumentException>(() => repo.Commits.QueryBy(new Filter{Since = string.Empty}));
}
}

[Test]
public void PushingNullShaThrows()
{
using (var repo = new Repository(Constants.TestRepoPath))
{
Assert.Throws<ArgumentNullException>(() => repo.Commits.QueryBy(new Filter { Since = null }));
}
}
}
}
7 changes: 6 additions & 1 deletion LibGit2Sharp.Tests/RepositoryFixture.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Linq;
using LibGit2Sharp.Tests.TestHelpers;
using NUnit.Framework;

Expand Down Expand Up @@ -57,7 +58,11 @@ private static void AssertInitializedRepository(Repository repo)
repo.Info.IsHeadDetached.ShouldBeFalse();
repo.Head.TargetIdentifier.ShouldEqual("refs/heads/master");
repo.Head.ResolveToDirectReference().ShouldBeNull();
Assert.Throws<InvalidOperationException>(() => { var c = repo.Commits; });

repo.Commits.Count().ShouldEqual(0);
repo.Commits.QueryBy(new Filter { Since = repo.Head }).Count().ShouldEqual(0);
repo.Commits.QueryBy(new Filter { Since = "HEAD" }).Count().ShouldEqual(0);
repo.Commits.QueryBy(new Filter { Since = "refs/heads/master" }).Count().ShouldEqual(0);
}

[Test]
Expand Down
16 changes: 14 additions & 2 deletions LibGit2Sharp/CommitCollection.cs
Expand Up @@ -9,7 +9,7 @@ namespace LibGit2Sharp
/// <summary>
/// A collection of commits in a <see cref = "Repository" />
/// </summary>
public class CommitCollection : ICommitCollection
public class CommitCollection : IQueryableCommitCollection
{
private readonly Repository repo;
private ObjectId pushedObjectId;
Expand Down Expand Up @@ -80,7 +80,14 @@ public ICommitCollection QueryBy(Filter filter)
Ensure.ArgumentNotNull(filter, "filter");
Ensure.ArgumentNotNull(filter.Since, "filter.Since");

GitObject gitObj = repo.Lookup(filter.Since.ToString());
string shaOrRefName = filter.Since.ToString();

if ((repo.Info.IsEmpty) && PointsAtTheHead(shaOrRefName))
{
return new EmptyCommitCollection(filter.SortBy);
}

GitObject gitObj = repo.Lookup(shaOrRefName);

if (gitObj == null) // TODO: Should we check the type? Git-log allows TagAnnotation oid as parameter. But what about Blobs and Trees?
{
Expand All @@ -90,6 +97,11 @@ public ICommitCollection QueryBy(Filter filter)
return new CommitCollection(repo, filter.SortBy) { pushedObjectId = gitObj.Id };
}

private static bool PointsAtTheHead(string shaOrRefName)
{
return ("HEAD".Equals(shaOrRefName, StringComparison.Ordinal) || "refs/heads/master".Equals(shaOrRefName, StringComparison.Ordinal));
}

#region Nested type: CommitEnumerator

private class CommitEnumerator : IEnumerator<Commit>
Expand Down
53 changes: 53 additions & 0 deletions LibGit2Sharp/EmptyCommitCollection.cs
@@ -0,0 +1,53 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace LibGit2Sharp
{
internal class EmptyCommitCollection : IQueryableCommitCollection
{
internal EmptyCommitCollection(GitSortOptions sortedBy)
{
SortedBy = sortedBy;
}

/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>1</filterpriority>
public IEnumerator<Commit> GetEnumerator()
{
return Enumerable.Empty<Commit>().GetEnumerator();
}

/// <summary>
/// Returns the list of commits of the repository matching the specified <paramref name="filter"/>.
/// </summary>
/// <param name="filter">The options used to control which commits will be returned.</param>
/// <returns>A collection of commits, ready to be enumerated.</returns>
public ICommitCollection QueryBy(Filter filter)
{
return new EmptyCommitCollection(filter.SortBy);
}

/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>2</filterpriority>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

/// <summary>
/// Gets the current sorting strategy applied when enumerating the collection.
/// </summary>
public GitSortOptions SortedBy { get; private set; }
}
}
2 changes: 1 addition & 1 deletion LibGit2Sharp/ICommitCollection.cs
Expand Up @@ -5,7 +5,7 @@ namespace LibGit2Sharp
public interface ICommitCollection : IEnumerable<Commit>
{
/// <summary>
/// Gets the current sorting strategy applied when enumerating the collection
/// Gets the current sorting strategy applied when enumerating the collection.
/// </summary>
GitSortOptions SortedBy { get; }
}
Expand Down
12 changes: 12 additions & 0 deletions LibGit2Sharp/IQueryableCommitCollection.cs
@@ -0,0 +1,12 @@
namespace LibGit2Sharp
{
public interface IQueryableCommitCollection : ICommitCollection
{
/// <summary>
/// Returns the list of commits of the repository matching the specified <paramref name="filter"/>.
/// </summary>
/// <param name="filter">The options used to control which commits will be returned.</param>
/// <returns>A collection of commits, ready to be enumerated.</returns>
ICommitCollection QueryBy(Filter filter);
}
}
2 changes: 2 additions & 0 deletions LibGit2Sharp/LibGit2Sharp.csproj
Expand Up @@ -71,6 +71,7 @@
<Compile Include="DirectReference.cs" />
<Compile Include="Core\GitIndexTime.cs" />
<Compile Include="Core\GitIndexEntry.cs" />
<Compile Include="EmptyCommitCollection.cs" />
<Compile Include="GitObject.cs" />
<Compile Include="GitObjectType.cs" />
<Compile Include="GitSortOptions.cs" />
Expand All @@ -82,6 +83,7 @@
<Compile Include="Core\IndexSafeHandle.cs" />
<Compile Include="IndexEntryState.cs" />
<Compile Include="Filter.cs" />
<Compile Include="IQueryableCommitCollection.cs" />
<Compile Include="ObjectId.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Reference.cs" />
Expand Down
8 changes: 4 additions & 4 deletions LibGit2Sharp/Repository.cs
Expand Up @@ -49,7 +49,7 @@ internal RepositorySafeHandle Handle
/// Shortcut to return the reference to HEAD
/// </summary>
/// <returns></returns>

public Reference Head
{
get { return Refs["HEAD"]; }
Expand All @@ -75,9 +75,9 @@ public ReferenceCollection Refs
/// Lookup and enumerate commits in the repository.
/// Iterating this collection directly starts walking from the HEAD.
/// </summary>
public CommitCollection Commits
public IQueryableCommitCollection Commits
{
get { return (CommitCollection)commits.QueryBy(new Filter{Since = Head}); }
get { return (IQueryableCommitCollection)commits.QueryBy(new Filter { Since = Head }); }
}

/// <summary>
Expand Down Expand Up @@ -219,7 +219,7 @@ public GitObject Lookup(string shaOrReferenceName, GitObjectType type = GitObjec

private static bool IsReferencePeelable(Reference reference)
{
return reference != null && ((reference is DirectReference) ||(reference is SymbolicReference && ((SymbolicReference)reference).Target != null));
return reference != null && ((reference is DirectReference) || (reference is SymbolicReference && ((SymbolicReference)reference).Target != null));
}
}
}

0 comments on commit 3034aa9

Please sign in to comment.