Skip to content

Commit

Permalink
Made status take into account master branch if not on it
Browse files Browse the repository at this point in the history
  • Loading branch information
jokedst committed Sep 8, 2018
1 parent f679bed commit c112d71
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 46 deletions.
2 changes: 1 addition & 1 deletion ATray/MainWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public void CreateRepositoryMenyEntries()

private void UpdateIcon()
{
var worstStatus = _repositoryCollection.Select(x => x.LastStatus.ToOverallStatus()).OrderBy(x=>x).LastOrDefault();
var worstStatus = _repositoryCollection.WorstStatus().ToOverallStatus();
if (worstStatus == _overallStatus) return;
_overallStatus = worstStatus;
switch (_overallStatus)
Expand Down
21 changes: 4 additions & 17 deletions ATray/Tools/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,10 @@ public static class Extensions
{
public static OverallStatusType ToOverallStatus(this RepoStatus status)
{
switch (status)
{
case RepoStatus.Conflict:
return OverallStatusType.CodeRed;
case RepoStatus.Behind:
return OverallStatusType.WarnBehind;
case RepoStatus.Dirty:
return OverallStatusType.WarnAhead;
default:
return OverallStatusType.Ok;
}
}

public static OverallStatusType WorstOf(this OverallStatusType overallStatus,RepoStatus status)
{
var converted = status.ToOverallStatus();
return converted > overallStatus ? converted : overallStatus;
if (status >= RepoStatus.Mergeable) return OverallStatusType.CodeRed;
if (status >= RepoStatus.Behind) return OverallStatusType.WarnBehind;
if (status >= RepoStatus.Dirty) return OverallStatusType.WarnAhead;
return OverallStatusType.Ok;
}

public static Color ToColor(OverallStatusType overallStatus)
Expand Down
Binary file modified RepositoryManager.Tests/TestRepos.zip
Binary file not shown.
42 changes: 32 additions & 10 deletions RepositoryManager.Tests/The_RepositoryCollection.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace RepositoryManager.Tests
using RepositoryManager.Git;

namespace RepositoryManager.Tests
{
using System.IO;
using System.IO.Compression;
Expand All @@ -10,6 +12,7 @@
public class RepositoryCollectionFacts
{
private string _path;
protected string dir(string repo) => Path.Combine(_path, repo);

[OneTimeSetUp]
public void Prepair()
Expand All @@ -33,7 +36,8 @@ public void can_find_repos_xps()
var repos = RepositoryCollection.FindRepositories(_path);

Assert.True(repos.Any(x => x.Name == "Clean"));
Assert.AreEqual(2, repos.Count);
Assert.True(repos.Any(x => x.Name == "Dirty"));
Assert.True(repos.Any(x => x.Name == "OnLocalBranch"));
}

[Test]
Expand All @@ -42,16 +46,34 @@ public void can_find_git_repos()
var repos = RepositoryCollection.FindRepositories(_path, RepositoryType.Git);

Assert.True(repos.Any(x => x.Name == "Clean"));
Assert.AreEqual(2, repos.Count);
Assert.True(repos.Any(x => x.Name == "Dirty"));
Assert.True(repos.Any(x => x.Name == "OnLocalBranch"));
}

//[Test]
//public void can_find_svn_repos()
//{
// var repos = RepositoryCollection.FindRepositories(_path, RepositoryType.Svn);
[Test]
public void can_get_dirty_status_from_dir()
{
var dirty = new GitRepository(dir("Dirty"));
var status = dirty.RefreshRemoteStatus();
Assert.AreEqual(RepoStatus.Dirty,status);
}

// Assert.True(repos.Any(x => x.Name == "svnClean"));
// Assert.AreEqual(3, repos.Count);
//}
[Test]
public void Status_behind_if_master_behind_when_on_local_branch()
{
var dirty = new GitRepository(dir("BranchDetachedMasterBehind"));
var status = dirty.RefreshRemoteStatus();
Assert.AreEqual(RepoStatus.Behind, status);
}

[Test]
public void can_add_repos_and_check_status()
{
var repos = new RepositoryCollection();
var branchedRepo = new GitRepository(dir("OnLocalBranch"));
branchedRepo.RefreshLocalStatus();
repos.Add(branchedRepo);
Assert.AreEqual(RepoStatus.Clean, repos.WorstStatus());
}
}
}
40 changes: 33 additions & 7 deletions RepositoryManager/Git/GitRepository.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using SharpSvn.Remote;

namespace RepositoryManager.Git
{
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using LibGit2Sharp;
using LibGit2Sharp.Handlers;

Expand Down Expand Up @@ -84,19 +87,24 @@ public GitRepository(string location, string name, DateTime lastStatusAt, Schedu
}

/// <inheritdoc />
public RepoStatus UpdateStatus()
public RepoStatus RefreshRemoteStatus()
{
var stopwatch = Stopwatch.StartNew();
try
{
using (var repo = new Repository(Location))
{
if (!repo.Head.IsTracking) return LastStatus = RepoStatus.Disconnected;
if (!repo.Network.Remotes.Any())
{
RefreshLocalStatus();
return LastStatus;
}
//if (!repo.Head.IsTracking) return LastStatus = RepoStatus.Disconnected;
var credentialHelper = repo.Config.Get<string>("credential.helper");
var origin = repo.Network.Remotes[repo.Head.RemoteName];
var origin = repo.Network.Remotes.FirstOrDefault(r=>r.Name == (repo.Head.RemoteName ?? "origin"));
if (origin == null) return RepoStatus.Error;
var fetchOptions = new FetchOptions();
if (!origin.Url.Contains("://"))
if (Regex.IsMatch(origin.Url, @"(^ssh://|@.*:)"))
throw new Exception("git over SSH is not aupported by Atray");
if (credentialHelper?.Value == "wincred")
fetchOptions.CredentialsProvider = CredentialsProvider.WinCred;
Expand Down Expand Up @@ -134,12 +142,30 @@ public void RefreshLocalStatus()
using (var repo = new Repository(Location))
{
var status = repo.RetrieveStatus(new StatusOptions());

var dirty = status.IsDirty;
var behind = (repo.Head.TrackingDetails.BehindBy ?? 0) != 0;
var ahead = (repo.Head.TrackingDetails.AheadBy ?? 0) != 0;

// If current branch isn't tracking these two will be zero
var behind = repo.Head.TrackingDetails.BehindBy > 0;
var ahead = repo.Head.TrackingDetails.AheadBy > 0;

// Common work states:
// * On master, ahead or behind
// * On tracking branch, ahead/behind tracking, but behind master is important too
// * On local branch, clean/dirty, ahead/behind master
if (repo.Head.FriendlyName != "master" && repo.Branches.Any(b => b.FriendlyName == "master"))
{
var master = repo.Branches["master"];
if (master.IsTracking)
{
// This only checks the local master vs remote master
behind = behind || master.TrackingDetails.BehindBy > 0;
ahead = ahead || master.TrackingDetails.AheadBy > 0;
// TODO: compare local branch to remote master?
}
}

var repoStatus = RepoStatusFlags.Clean;
if (!repo.Network.Remotes.Any()) repoStatus |= RepoStatusFlags.Disconnected;
if (dirty) repoStatus |= RepoStatusFlags.LocalChanges;
if (behind) repoStatus |= RepoStatusFlags.RemoteUnmergedCommits;
if (ahead) repoStatus |= RepoStatusFlags.LocalUnpushedCommits;
Expand Down
6 changes: 6 additions & 0 deletions RepositoryManager/IRepositoryCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,11 @@ public interface IRepositoryCollection : IEnumerable<ISourceRepository>
/// </summary>
/// <param name="repository"> Repo that was modified. Must be part of collection already </param>
void RepositoryModified(ISourceRepository repository);

/// <summary>
/// Returns the highest ("worst") status of all repositories.
/// </summary>
/// <returns>Status of the repo with highest status, or Unknown if no repos are registered</returns>
RepoStatus WorstStatus();
}
}
2 changes: 1 addition & 1 deletion RepositoryManager/ISourceRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public interface ISourceRepository

/// <summary> Updates the status </summary>
/// <returns></returns>
RepoStatus UpdateStatus();
RepoStatus RefreshRemoteStatus();

/// <summary>
/// Updates the dir with remote changes
Expand Down
15 changes: 8 additions & 7 deletions RepositoryManager/RepoStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,29 @@ namespace RepositoryManager
using System;

/// <summary>
/// Current (or last known) status on a repository
/// Current (or last known) status on a repository.
/// Roughly in order of severity (higher value = more important)
/// </summary>
public enum RepoStatus
{
/// <summary> Update has never run </summary>
Unknown,
Unknown = 0,
/// <summary> No origin set </summary>
Disconnected,
/// <summary> No local changes, up to date with remote </summary>
Clean,
/// <summary> Local changes only </summary>
Dirty,
/// <summary> Local commits are not pushed </summary>
Ahead,
/// <summary> No local changes, behind remote </summary>
Behind,
/// <summary> Local changes and remote updates. Can not merge cleanly or haven't tried </summary>
Conflict,
/// <summary> Local changes and remote updates. Can merge cleanly </summary>
Mergeable,
/// <summary> Local changes and remote updates. Can not merge cleanly or haven't tried </summary>
Conflict,
/// <summary> Could not retrieve status </summary>
Error,
/// <summary> Local commits are not pushed </summary>
Ahead
Error
}

/// <summary>
Expand Down
22 changes: 20 additions & 2 deletions RepositoryManager/RepositoryCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,17 @@ public class RepositoryCollection : IRepositoryCollection

private FileListeningMode _useFileListeners;
private readonly Dictionary<string, DelayedFileSystemWatcher> _fileListeners = new Dictionary<string, DelayedFileSystemWatcher>();


/// <summary>
/// Creates a new empty <see cref="RepositoryCollection"/>
/// </summary>
public RepositoryCollection()
{
_repositories=new List<ISourceRepository>();
_repositoriesByName = new Dictionary<string, ISourceRepository>();
_timer = new Timer(TimerTick, null, SampleFrequency, SampleFrequency);
}

/// <summary>
/// Load a reposet from a file
/// </summary>
Expand Down Expand Up @@ -271,7 +281,7 @@ private void CheckRepo(ISourceRepository repo)
if (repo.LastStatusAt.AddMinutes((int) repo.UpdateSchedule) >= DateTime.Now)
return;
var previousStatus = repo.LastStatus;
repo.UpdateStatus();
repo.RefreshRemoteStatus();
var eventArgs = new RepositoryEventArgs(repo.Location, previousStatus, repo.LastStatus, repo.Name, RepositoryEventType.Updated);
OnRepositoryUpdated(eventArgs);

Expand Down Expand Up @@ -398,6 +408,14 @@ public void SetFileListening(FileListeningMode mode)
}
}
}

/// <summary>
/// Returns the highest ("worst") status of all repositories.
/// </summary>
/// <returns>Status of the repo with highest status, or Unknown if no repos are registered</returns>
public RepoStatus WorstStatus()
=> _repositories?.Aggregate(RepoStatus.Unknown, (status, repo) => repo.LastStatus > status ? repo.LastStatus : status)
?? RepoStatus.Unknown;
}

/// <summary> Delegate for repo update events </summary>
Expand Down
2 changes: 1 addition & 1 deletion RepositoryManager/Svn/SvnRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public bool Valid()
}

/// <inheritdoc/>
public RepoStatus UpdateStatus()
public RepoStatus RefreshRemoteStatus()
{
var stopwatch = Stopwatch.StartNew();
using (SvnClient client = new SvnClient())
Expand Down

0 comments on commit c112d71

Please sign in to comment.