Skip to content

Commit

Permalink
Enable filtering for name, branch and path
Browse files Browse the repository at this point in the history
Use prefixes 'n ' for names (optional), 'b ' for branches and 'p ' for paths.
Fixes #68
  • Loading branch information
awaescher committed Apr 1, 2019
1 parent 70eb38b commit ad022c2
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 36 deletions.
86 changes: 60 additions & 26 deletions RepoZ.Api/Git/RepositoryView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Diagnostics;
using System.Globalization;
using System.ComponentModel;
using System.Text.RegularExpressions;

namespace RepoZ.Api.Git
{
Expand All @@ -26,6 +27,65 @@ public RepositoryView(Repository repository)
UpdateStampUtc = DateTime.UtcNow;
}

public bool MatchesRegexFilter(string pattern) => MatchesFilter(pattern, useRegex: true);

public bool MatchesFilter(string filter) => MatchesFilter(filter, useRegex: false);

private bool MatchesFilter(string filter, bool useRegex)
{
if (string.IsNullOrEmpty(filter))
return true;

string filterProperty = null;

if (filter.StartsWith("n ", StringComparison.OrdinalIgnoreCase))
filterProperty = Name;
else if (filter.StartsWith("b ", StringComparison.OrdinalIgnoreCase))
filterProperty = CurrentBranch;
else if (filter.StartsWith("p ", StringComparison.OrdinalIgnoreCase))
filterProperty = Path;

if (filterProperty == null)
filterProperty = Name;
else
filter = filter.Substring(2);

if (string.IsNullOrEmpty(filter))
return true;

if (useRegex)
return Regex.IsMatch(filterProperty, filter, RegexOptions.IgnoreCase);

return filterProperty.IndexOf(filter, StringComparison.OrdinalIgnoreCase) > -1;
}

public override bool Equals(object obj)
{
var other = obj as RepositoryView;

if (other != null)
return other.Repository.Equals(this.Repository);

return object.ReferenceEquals(this, obj);
}

private void EnsureStatusCache()
{
var repositoryStatusCode = Repository.GetStatusCode();

// compare the status code and not the full status string because the latter one is heavier to calculate
bool canTakeFromCache = _cachedRepositoryStatusCode == repositoryStatusCode;

if (!canTakeFromCache)
{
var compressor = new StatusCompressor(new StatusCharacterMap());
_cachedRepositoryStatus = compressor.Compress(Repository);
_cachedRepositoryStatusWithBranch = compressor.CompressWithBranch(Repository);

_cachedRepositoryStatusCode = repositoryStatusCode;
}
}

public string Name => (Repository.Name ?? "") + (IsSynchronizing ? SyncAppendix : "");

public string Path => Repository.Path ?? "";
Expand Down Expand Up @@ -92,31 +152,5 @@ public bool IsSynchronizing

public DateTime UpdateStampUtc { get; private set; }

public override bool Equals(object obj)
{
var other = obj as RepositoryView;

if (other != null)
return other.Repository.Equals(this.Repository);

return object.ReferenceEquals(this, obj);
}

private void EnsureStatusCache()
{
var repositoryStatusCode = Repository.GetStatusCode();

// compare the status code and not the full status string because the latter one is heavier to calculate
bool canTakeFromCache = _cachedRepositoryStatusCode == repositoryStatusCode;

if (!canTakeFromCache)
{
var compressor = new StatusCompressor(new StatusCharacterMap());
_cachedRepositoryStatus = compressor.Compress(Repository);
_cachedRepositoryStatusWithBranch = compressor.CompressWithBranch(Repository);

_cachedRepositoryStatusCode = repositoryStatusCode;
}
}
}
}
12 changes: 6 additions & 6 deletions RepoZ.App.Win/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,13 @@ public Ipc.Repository[] GetMatchingRepositories(string repositoryNamePattern)
{
var aggregator = TinyIoCContainer.Current.Resolve<IRepositoryInformationAggregator>();
return aggregator.Repositories
.Where(r => string.IsNullOrEmpty(repositoryNamePattern) || Regex.IsMatch(r.Name, repositoryNamePattern, RegexOptions.IgnoreCase))
.Where(r => r.MatchesRegexFilter(repositoryNamePattern))
.Select(r => new Ipc.Repository
{
Name = r.Name,
BranchWithStatus = r.BranchWithStatus,
Path = r.Path
})
{
Name = r.Name,
BranchWithStatus = r.BranchWithStatus,
Path = r.Path
})
.ToArray();
}

Expand Down
5 changes: 1 addition & 4 deletions RepoZ.App.Win/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,7 @@ private void txtFilter_TextChanged(object sender, TextChangedEventArgs e)

private bool FilterRepositories(object item)
{
if (String.IsNullOrEmpty(txtFilter.Text))
return true;
else
return (item as RepositoryView).Name.IndexOf(txtFilter.Text, StringComparison.OrdinalIgnoreCase) > -1;
return (item as RepositoryView)?.MatchesFilter(txtFilter.Text) ?? false;
}

private void txtFilter_Finish(object sender, EventArgs e)
Expand Down
62 changes: 62 additions & 0 deletions Tests/UI/RepositoryViewTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,68 @@ public void Returns_The_Compressed_String_From_The_StatusCompressor_Helper_Class
}
}

public class MatchesFilterMethod : RepositoryViewTests
{
[Test]
public void Returns_True_If_Filter_Is_Empty()
{
_view.MatchesFilter("").Should().Be(true);
}

[Test]
public void Can_Filter_By_Name_Implicit()
{
_repo.Name = "Hello World";
_view.MatchesFilter("lo wo").Should().Be(true);
}

[Test]
public void Can_Filter_By_Name_Explicit()
{
_repo.Name = "Hello World";
_view.MatchesFilter("n lo wo").Should().Be(true);
}

[Test]
public void Can_Filter_By_Branch()
{
_repo.Name = "No Match Here";
_repo.CurrentBranch = "feature/Test";
_view.MatchesFilter("b feat").Should().Be(true);
}

[Test]
public void Can_Filter_By_Path()
{
_repo.Name = "No Match Here";
_repo.Path = @"C:\Test\Path";
_view.MatchesFilter(@"p C:\").Should().Be(true);
}

[Test]
public void Returns_True_If_Filter_Is_Empty_Except_Prefix()
{
// "n ", "b ", "p " can be used to filter for name, branch and path
_view.MatchesFilter("b ").Should().Be(true);
}

[Test]
public void Returns_False_If_Prefix_Misses_Space()
{
// should be interpreted as "b" search term without prefix
_repo.Name = "xyz";
_view.MatchesFilter("b").Should().Be(false);
}

[Test]
public void Returns_False_If_Prefix_Comes_With_Two_Spaces()
{
// trimming "b " leads to " master" which is not trimmed by design
_repo.CurrentBranch = "master";
_view.MatchesFilter("b master").Should().Be(false);
}
}

public class WasFoundProperty : RepositoryViewTests
{
[Test]
Expand Down

0 comments on commit ad022c2

Please sign in to comment.