Skip to content

Commit

Permalink
Add in glob filters to push and hide during revwalk
Browse files Browse the repository at this point in the history
  • Loading branch information
tclem committed Jun 15, 2012
1 parent 8e8d228 commit ac04feb
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 48 deletions.
22 changes: 22 additions & 0 deletions LibGit2Sharp.Tests/CommitFixture.cs
Expand Up @@ -289,6 +289,28 @@ public void CanEnumerateCommitsFromMixedStartingPoints()
});
}

[Fact]
public void CanEnumerateCommitsUsingGlob()
{
AssertEnumerationOfCommits(
repo => new Filter { SinceGlob = "heads" },
new[]
{
"4c062a6", "e90810b", "6dcf9bf", "a4a7dce", "be3563a", "c47800c", "9fd738e", "4a202b3", "41bc8c6", "5001298", "5b5b025", "8496071"
});
}

[Fact]
public void CanHideCommitsUsingGlob()
{
AssertEnumerationOfCommits(
repo => new Filter { Since = "refs/heads/packed-test", UntilGlob = "packed" },
new[]
{
"4a202b3", "5b5b025", "8496071"
});
}

[Fact]
public void CanEnumerateCommitsFromAnAnnotatedTag()
{
Expand Down
71 changes: 24 additions & 47 deletions LibGit2Sharp/CommitCollection.cs
Expand Up @@ -13,38 +13,36 @@ namespace LibGit2Sharp
/// </summary>
public class CommitCollection : IQueryableCommitCollection
{
private readonly Repository repo;
private IList<object> includedIdentifier = new List<object> { "HEAD" };
private IList<object> excludedIdentifier = new List<object>();
private readonly GitSortOptions sortOptions;
readonly Repository repo;
readonly Filter queryFilter;

/// <summary>
/// Initializes a new instance of the <see cref = "CommitCollection" /> class.
/// The commits will be enumerated according in reverse chronological order.
/// </summary>
/// <param name = "repo">The repository.</param>
internal CommitCollection(Repository repo)
: this(repo, GitSortOptions.Time)
: this(repo, new Filter{Since = "HEAD", SortBy = GitSortOptions.Time})
{
}

/// <summary>
/// Initializes a new instance of the <see cref = "CommitCollection" /> class.
/// </summary>
/// <param name = "repo">The repository.</param>
/// <param name = "sortingStrategy">The sorting strategy which should be applied when enumerating the commits.</param>
internal CommitCollection(Repository repo, GitSortOptions sortingStrategy)
/// <param name="queryFilter"> </param>
internal CommitCollection(Repository repo, Filter queryFilter)
{
this.repo = repo;
sortOptions = sortingStrategy;
this.queryFilter = queryFilter;
}

/// <summary>
/// Gets the current sorting strategy applied when enumerating the collection
/// </summary>
public GitSortOptions SortedBy
{
get { return sortOptions; }
get { return queryFilter.SortBy; }
}

#region IEnumerable<Commit> Members
Expand All @@ -55,12 +53,12 @@ public GitSortOptions SortedBy
/// <returns>An <see cref = "IEnumerator{T}" /> object that can be used to iterate through the collection.</returns>
public IEnumerator<Commit> GetEnumerator()
{
if ((repo.Info.IsEmpty) && includedIdentifier.Any(o => PointsAtTheHead(o.ToString()))) // TODO: ToString() == fragile
if ((repo.Info.IsEmpty) && queryFilter.SinceList.Any(o => PointsAtTheHead(o.ToString()))) // TODO: ToString() == fragile
{
return Enumerable.Empty<Commit>().GetEnumerator();
}

return new CommitEnumerator(repo, includedIdentifier, excludedIdentifier, sortOptions);
return new CommitEnumerator(repo, this);
}

/// <summary>
Expand All @@ -85,38 +83,7 @@ public ICommitCollection QueryBy(Filter filter)
Ensure.ArgumentNotNull(filter.Since, "filter.Since");
Ensure.ArgumentNotNullOrEmptyString(filter.Since.ToString(), "filter.Since");

return new CommitCollection(repo, filter.SortBy)
{
includedIdentifier = ToList(filter.Since),
excludedIdentifier = ToList(filter.Until)
};
}

private static IList<object> ToList(object obj)
{
var list = new List<object>();

if (obj == null)
{
return list;
}

var types = new[]
{
typeof(string), typeof(ObjectId),
typeof(Commit), typeof(TagAnnotation),
typeof(Tag), typeof(Branch), typeof(DetachedHead),
typeof(Reference), typeof(DirectReference), typeof(SymbolicReference)
};

if (types.Contains(obj.GetType()))
{
list.Add(obj);
return list;
}

list.AddRange(((IEnumerable)obj).Cast<object>());
return list;
return new CommitCollection(repo, filter);
}

private static bool PointsAtTheHead(string shaOrRefName)
Expand Down Expand Up @@ -240,17 +207,27 @@ private class CommitEnumerator : IEnumerator<Commit>
private readonly RevWalkerSafeHandle handle;
private ObjectId currentOid;

public CommitEnumerator(Repository repo, IList<object> includedIdentifier, IList<object> excludedIdentifier, GitSortOptions sortingStrategy)
public CommitEnumerator(Repository repo, CommitCollection commits)
{
this.repo = repo;
int res = NativeMethods.git_revwalk_new(out handle, repo.Handle);
repo.RegisterForCleanup(handle);

Ensure.Success(res);

Sort(sortingStrategy);
Push(includedIdentifier);
Hide(excludedIdentifier);
Sort(commits.SortedBy);
Push(commits.queryFilter.SinceList);
Hide(commits.queryFilter.UntilList);

if(!string.IsNullOrEmpty(commits.queryFilter.SinceGlob))
{
Ensure.Success(NativeMethods.git_revwalk_push_glob(handle, commits.queryFilter.SinceGlob));
}

if(!string.IsNullOrEmpty(commits.queryFilter.UntilGlob))
{
Ensure.Success(NativeMethods.git_revwalk_hide_glob(handle, commits.queryFilter.UntilGlob));
}
}

#region IEnumerator<Commit> Members
Expand Down
6 changes: 6 additions & 0 deletions LibGit2Sharp/Core/NativeMethods.cs
Expand Up @@ -592,6 +592,9 @@ public static bool RepositoryStateChecker(RepositorySafeHandle repositoryPtr, Fu
[DllImport(libgit2)]
public static extern int git_revwalk_hide(RevWalkerSafeHandle walker, ref GitOid oid);

[DllImport(libgit2)]
public static extern int git_revwalk_hide_glob(RevWalkerSafeHandle walker, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string glob);

[DllImport(libgit2)]
public static extern int git_revwalk_new(out RevWalkerSafeHandle walker, RepositorySafeHandle repo);

Expand All @@ -601,6 +604,9 @@ public static bool RepositoryStateChecker(RepositorySafeHandle repositoryPtr, Fu
[DllImport(libgit2)]
public static extern int git_revwalk_push(RevWalkerSafeHandle walker, ref GitOid oid);

[DllImport(libgit2)]
public static extern int git_revwalk_push_glob(RevWalkerSafeHandle walker, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string glob);

[DllImport(libgit2)]
public static extern void git_revwalk_reset(RevWalkerSafeHandle walker);

Expand Down
69 changes: 68 additions & 1 deletion LibGit2Sharp/Filter.cs
@@ -1,10 +1,17 @@
namespace LibGit2Sharp
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace LibGit2Sharp
{
/// <summary>
/// Criterias used to filter out and order the commits of the repository when querying its history.
/// </summary>
public class Filter
{
IList<object> sinceList;
IList<object> untilList;

/// <summary>
/// Initializes a new instance of <see cref = "Filter" />.
/// </summary>
Expand Down Expand Up @@ -33,6 +40,23 @@ public Filter()
/// </summary>
public object Since { get; set; }


/// <summary>
/// Return a parsed list of Since objects.
/// </summary>
public IList<object> SinceList
{
get
{
return sinceList ?? (sinceList = ToList(Since));
}
}

/// <summary>
/// A string glob to using as a starting point for the revwalk.
/// </summary>
public string SinceGlob { get; set; }

/// <summary>
/// A pointer to a commit object or a list of pointers which will be excluded (along with ancestors) from the enumeration.
/// <para>
Expand All @@ -42,5 +66,48 @@ public Filter()
/// </para>
/// </summary>
public object Until { get; set; }

/// <summary>
/// Return a parsed list of Until objects.
/// </summary>
public IList<object> UntilList
{
get
{
return untilList ?? (untilList = ToList(Until));
}
}

/// <summary>
/// A string glob to hide from the revwalk.
/// </summary>
public string UntilGlob { get; set; }

static IList<object> ToList(object obj)
{
var list = new List<object>();

if (obj == null)
{
return list;
}

var types = new[]
{
typeof(string), typeof(ObjectId),
typeof(Commit), typeof(TagAnnotation),
typeof(Tag), typeof(Branch), typeof(DetachedHead),
typeof(Reference), typeof(DirectReference), typeof(SymbolicReference)
};

if (types.Contains(obj.GetType()))
{
list.Add(obj);
return list;
}

list.AddRange(((IEnumerable)obj).Cast<object>());
return list;
}
}
}

0 comments on commit ac04feb

Please sign in to comment.