Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.

Commit 679719b

Browse files
Merge branch 'master' into fixes/default-struct-null-check
2 parents bc07cbf + e41f883 commit 679719b

File tree

17 files changed

+421
-125
lines changed

17 files changed

+421
-125
lines changed

src/GitHub.Api/Cache/CacheInterfaces.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ public interface IGitUserCache : IManagedCache
5555

5656
public interface IGitStatusCache : IManagedCache
5757
{
58-
GitStatus GitStatus { get; set; }
58+
int Ahead { get; set; }
59+
int Behind { get; set; }
60+
List<GitStatusEntry> Entries { get; set; }
5961
}
6062

6163
public interface ILocalConfigBranchDictionary : IDictionary<string, ConfigBranch>

src/GitHub.Api/Extensions/GitStatusExtensions.cs

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
3+
namespace GitHub.Unity
4+
{
5+
[Serializable]
6+
public struct GitAheadBehindStatus
7+
{
8+
public static GitAheadBehindStatus Default = new GitAheadBehindStatus();
9+
10+
public int ahead;
11+
public int behind;
12+
13+
public GitAheadBehindStatus(int ahead, int behind)
14+
{
15+
this.ahead = ahead;
16+
this.behind = behind;
17+
}
18+
19+
public int Ahead => ahead;
20+
21+
public int Behind => behind;
22+
}
23+
}

src/GitHub.Api/Git/GitClient.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ public interface IGitClient
1515

1616
ITask LfsInstall(IOutputProcessor<string> processor = null);
1717

18+
ITask<GitAheadBehindStatus> AheadBehindStatus(string gitRef, string otherRef,
19+
IOutputProcessor<GitAheadBehindStatus> processor = null);
20+
1821
ITask<GitStatus> Status(IOutputProcessor<GitStatus> processor = null);
1922

2023
ITask<string> GetConfig(string key, GitConfigSource configSource,
@@ -219,6 +222,14 @@ public ITask<GitStatus> Status(IOutputProcessor<GitStatus> processor = null)
219222
.Configure(processManager);
220223
}
221224

225+
public ITask<GitAheadBehindStatus> AheadBehindStatus(string gitRef, string otherRef, IOutputProcessor<GitAheadBehindStatus> processor = null)
226+
{
227+
Logger.Trace("AheadBehindStatus");
228+
229+
return new GitAheadBehindStatusTask(gitRef, otherRef, cancellationToken, processor)
230+
.Configure(processManager);
231+
}
232+
222233
public ITask<List<GitLogEntry>> Log(BaseOutputListProcessor<GitLogEntry> processor = null)
223234
{
224235
Logger.Trace("Log");

src/GitHub.Api/Git/IRepository.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ public interface IRepository : IEquatable<IRepository>
5757
/// Gets the current branch of the repository.
5858
/// </summary>
5959
GitBranch? CurrentBranch { get; }
60-
GitStatus CurrentStatus { get; }
60+
int CurrentAhead { get; }
61+
int CurrentBehind { get; }
62+
List<GitStatusEntry> CurrentChanges { get; }
6163
GitRemote[] Remotes { get; }
6264
GitBranch[] LocalBranches { get; }
6365
GitBranch[] RemoteBranches { get; }

src/GitHub.Api/Git/Repository.cs

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ public void Initialize(IRepositoryManager initRepositoryManager)
4949
repositoryManager = initRepositoryManager;
5050
repositoryManager.CurrentBranchUpdated += RepositoryManagerOnCurrentBranchUpdated;
5151
repositoryManager.GitStatusUpdated += RepositoryManagerOnGitStatusUpdated;
52+
repositoryManager.GitAheadBehindStatusUpdated += RepositoryManagerOnGitAheadBehindStatusUpdated;
5253
repositoryManager.GitLogUpdated += RepositoryManagerOnGitLogUpdated;
54+
repositoryManager.GitLocksUpdated += RepositoryManagerOnGitLocksUpdated;
5355
repositoryManager.LocalBranchesUpdated += RepositoryManagerOnLocalBranchesUpdated;
5456
repositoryManager.RemoteBranchesUpdated += RepositoryManagerOnRemoteBranchesUpdated;
5557
}
@@ -267,7 +269,7 @@ private void CacheContainer_OnCacheInvalidated(CacheType cacheType)
267269
break;
268270

269271
case CacheType.GitLocksCache:
270-
repositoryManager?.UpdateLocks();
272+
UpdateLocks();
271273
break;
272274

273275
case CacheType.GitUserCache:
@@ -353,26 +355,36 @@ private void RepositoryManagerOnCurrentBranchUpdated(ConfigBranch? branch, Confi
353355
new ActionTask(CancellationToken.None, () => {
354356
if (!Nullable.Equals(CurrentConfigBranch, branch))
355357
{
356-
var currentBranch = branch != null ? (GitBranch?)GetLocalGitBranch(branch.Value) : null;
358+
var currentBranch = branch != null ? (GitBranch?)GetLocalGitBranch(branch.Value) : null;
357359

358-
CurrentConfigBranch = branch;
359-
CurrentBranch = currentBranch;
360-
UpdateLocalBranches();
360+
CurrentConfigBranch = branch;
361+
CurrentBranch = currentBranch;
362+
UpdateLocalBranches();
361363
}
362364

363365
if (!Nullable.Equals(CurrentConfigRemote, remote))
364366
{
365-
CurrentConfigRemote = remote;
366-
CurrentRemote = GetGitRemote(remote.Value);
367-
ClearRepositoryInfo();
367+
CurrentConfigRemote = remote;
368+
CurrentRemote = remote.HasValue ? (GitRemote?)GetGitRemote(remote.Value) : null;
369+
ClearRepositoryInfo();
368370
}
369371
}) { Affinity = TaskAffinity.UI }.Start();
370372
}
371373

372374
private void RepositoryManagerOnGitStatusUpdated(GitStatus gitStatus)
373375
{
374376
new ActionTask(CancellationToken.None, () => {
375-
CurrentStatus = gitStatus;
377+
CurrentChanges = gitStatus.Entries;
378+
CurrentAhead = gitStatus.Ahead;
379+
CurrentBehind = gitStatus.Behind;
380+
}) { Affinity = TaskAffinity.UI }.Start();
381+
}
382+
383+
private void RepositoryManagerOnGitAheadBehindStatusUpdated(GitAheadBehindStatus aheadBehindStatus)
384+
{
385+
new ActionTask(CancellationToken.None, () => {
386+
CurrentAhead = aheadBehindStatus.Ahead;
387+
CurrentBehind = aheadBehindStatus.Behind;
376388
}) { Affinity = TaskAffinity.UI }.Start();
377389
}
378390

@@ -383,6 +395,14 @@ private void RepositoryManagerOnGitLogUpdated(List<GitLogEntry> gitLogEntries)
383395
}) { Affinity = TaskAffinity.UI }.Start();
384396
}
385397

398+
private void RepositoryManagerOnGitLocksUpdated(List<GitLock> gitLocks)
399+
{
400+
new ActionTask(CancellationToken.None, () => {
401+
CurrentLocks = gitLocks;
402+
})
403+
{ Affinity = TaskAffinity.UI }.Start();
404+
}
405+
386406
private void RepositoryManagerOnRemoteBranchesUpdated(Dictionary<string, ConfigRemote> remotes,
387407
Dictionary<string, Dictionary<string, ConfigBranch>> branches)
388408
{
@@ -401,6 +421,14 @@ private void RepositoryManagerOnLocalBranchesUpdated(Dictionary<string, ConfigBr
401421
}) { Affinity = TaskAffinity.UI }.Start();
402422
}
403423

424+
private void UpdateLocks()
425+
{
426+
if (CurrentRemote.HasValue)
427+
{
428+
repositoryManager?.UpdateLocks();
429+
}
430+
}
431+
404432
private void UpdateLocalBranches()
405433
{
406434
LocalBranches = LocalConfigBranches.Values.Select(GetLocalGitBranch).ToArray();
@@ -469,10 +497,22 @@ private ConfigRemote? CurrentConfigRemote
469497
set { cacheContainer.BranchCache.CurrentConfigRemote = value; }
470498
}
471499

472-
public GitStatus CurrentStatus
500+
public int CurrentAhead
501+
{
502+
get { return cacheContainer.GitStatusCache.Ahead; }
503+
private set { cacheContainer.GitStatusCache.Ahead = value; }
504+
}
505+
506+
public int CurrentBehind
507+
{
508+
get { return cacheContainer.GitStatusCache.Behind; }
509+
private set { cacheContainer.GitStatusCache.Behind = value; }
510+
}
511+
512+
public List<GitStatusEntry> CurrentChanges
473513
{
474-
get { return cacheContainer.GitStatusCache.GitStatus; }
475-
private set { cacheContainer.GitStatusCache.GitStatus = value; }
514+
get { return cacheContainer.GitStatusCache.Entries; }
515+
private set { cacheContainer.GitStatusCache.Entries = value; }
476516
}
477517

478518
public GitBranch? CurrentBranch

src/GitHub.Api/Git/RepositoryManager.cs

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,14 @@ public interface IRepositoryManager : IDisposable
3636
ITask UnlockFile(string file, bool force);
3737
void UpdateGitLog();
3838
void UpdateGitStatus();
39+
void UpdateGitAheadBehindStatus();
3940
void UpdateLocks();
4041
int WaitForEvents();
4142

4243
IGitConfig Config { get; }
4344
IGitClient GitClient { get; }
4445
bool IsBusy { get; }
46+
event Action<GitAheadBehindStatus> GitAheadBehindStatusUpdated;
4547
}
4648

4749
interface IRepositoryPathConfiguration
@@ -102,6 +104,7 @@ class RepositoryManager : IRepositoryManager
102104
public event Action<ConfigBranch?, ConfigRemote?> CurrentBranchUpdated;
103105
public event Action<bool> IsBusyChanged;
104106
public event Action<GitStatus> GitStatusUpdated;
107+
public event Action<GitAheadBehindStatus> GitAheadBehindStatusUpdated;
105108
public event Action<List<GitLock>> GitLocksUpdated;
106109
public event Action<List<GitLogEntry>> GitLogUpdated;
107110
public event Action<Dictionary<string, ConfigBranch>> LocalBranchesUpdated;
@@ -247,13 +250,13 @@ public ITask CreateBranch(string branch, string baseBranch)
247250
public ITask LockFile(string file)
248251
{
249252
var task = GitClient.Lock(file);
250-
return HookupHandlers(task, true, false);
253+
return HookupHandlers(task, true, false).Then(UpdateLocks);
251254
}
252255

253256
public ITask UnlockFile(string file, bool force)
254257
{
255258
var task = GitClient.Unlock(file, force);
256-
return HookupHandlers(task, true, false);
259+
return HookupHandlers(task, true, false).Then(UpdateLocks);
257260
}
258261

259262
public void UpdateGitLog()
@@ -282,6 +285,33 @@ public void UpdateGitStatus()
282285
}).Start();
283286
}
284287

288+
public void UpdateGitAheadBehindStatus()
289+
{
290+
ConfigBranch? configBranch;
291+
ConfigRemote? configRemote;
292+
GetCurrentBranchAndRemote(out configBranch, out configRemote);
293+
294+
if (configBranch.HasValue && configBranch.Value.Remote.HasValue)
295+
{
296+
var name = configBranch.Value.Name;
297+
var trackingName = configBranch.Value.IsTracking ? configBranch.Value.Remote.Value.Name + "/" + name : "[None]";
298+
299+
var task = GitClient.AheadBehindStatus(name, trackingName);
300+
task = HookupHandlers(task, true, false);
301+
task.Then((success, status) =>
302+
{
303+
if (success)
304+
{
305+
GitAheadBehindStatusUpdated?.Invoke(status);
306+
}
307+
}).Start();
308+
}
309+
else
310+
{
311+
GitAheadBehindStatusUpdated?.Invoke(GitAheadBehindStatus.Default);
312+
}
313+
}
314+
285315
public void UpdateLocks()
286316
{
287317
var task = GitClient.ListLocks(false);
@@ -346,16 +376,33 @@ private void SetupWatcher()
346376

347377
private void UpdateHead()
348378
{
349-
var head = repositoryPaths.DotGitHead.ReadAllLines().FirstOrDefault();
350-
Logger.Trace("UpdateHead: {0}", head ?? "[NULL]");
351-
UpdateCurrentBranchAndRemote(head);
379+
Logger.Trace("UpdateHead");
380+
UpdateCurrentBranchAndRemote();
352381
UpdateGitLog();
353382
}
354383

355-
private void UpdateCurrentBranchAndRemote(string head)
384+
private string GetCurrentHead()
356385
{
357-
ConfigBranch? branch = null;
386+
return repositoryPaths.DotGitHead.ReadAllLines().FirstOrDefault();
387+
}
388+
389+
private void UpdateCurrentBranchAndRemote()
390+
{
391+
ConfigBranch? branch;
392+
ConfigRemote? remote;
393+
GetCurrentBranchAndRemote(out branch, out remote);
394+
395+
Logger.Trace("CurrentBranch: {0}", branch.HasValue ? branch.Value.ToString() : "[NULL]");
396+
Logger.Trace("CurrentRemote: {0}", remote.HasValue ? remote.Value.ToString() : "[NULL]");
397+
CurrentBranchUpdated?.Invoke(branch, remote);
398+
}
358399

400+
private void GetCurrentBranchAndRemote(out ConfigBranch? branch, out ConfigRemote? remote)
401+
{
402+
branch = null;
403+
remote = null;
404+
405+
var head = GetCurrentHead();
359406
if (head.StartsWith("ref:"))
360407
{
361408
var branchName = head.Substring(head.IndexOf("refs/heads/") + "refs/heads/".Length);
@@ -368,7 +415,6 @@ private void UpdateCurrentBranchAndRemote(string head)
368415
}
369416

370417
var defaultRemote = "origin";
371-
ConfigRemote? remote = null;
372418

373419
if (branch.HasValue && branch.Value.IsTracking)
374420
{
@@ -388,10 +434,6 @@ private void UpdateCurrentBranchAndRemote(string head)
388434
remote = configRemotes.FirstOrDefault();
389435
}
390436
}
391-
392-
Logger.Trace("CurrentBranch: {0}", branch.HasValue ? branch.Value.ToString() : "[NULL]");
393-
Logger.Trace("CurrentRemote: {0}", remote.HasValue ? remote.Value.ToString() : "[NULL]");
394-
CurrentBranchUpdated?.Invoke(branch, remote);
395437
}
396438

397439
private void WatcherOnRemoteBranchesChanged()
@@ -410,6 +452,7 @@ private void WatcherOnRepositoryCommitted()
410452
{
411453
Logger.Trace("WatcherOnRepositoryCommitted");
412454
UpdateGitLog();
455+
UpdateGitAheadBehindStatus();
413456
}
414457

415458
private void WatcherOnRepositoryChanged()
@@ -508,6 +551,8 @@ private void UpdateRemoteBranches()
508551

509552
Logger.Trace("OnRemoteBranchListUpdated {0} remotes", remotes.Count);
510553
RemoteBranchesUpdated?.Invoke(remotes, remoteBranches);
554+
555+
UpdateGitAheadBehindStatus();
511556
}
512557

513558
private bool disposed;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Threading;
2+
3+
namespace GitHub.Unity
4+
{
5+
class GitAheadBehindStatusTask : ProcessTask<GitAheadBehindStatus>
6+
{
7+
private const string TaskName = "git rev-list";
8+
private readonly string arguments;
9+
10+
public GitAheadBehindStatusTask(string gitRef, string otherRef,
11+
CancellationToken token, IOutputProcessor<GitAheadBehindStatus> processor = null)
12+
: base(token, processor ?? new GitAheadBehindStatusOutputProcessor())
13+
{
14+
Name = TaskName;
15+
arguments = $"rev-list --left-right --count {gitRef}...{otherRef}";
16+
}
17+
18+
public override string ProcessArguments => arguments;
19+
public override TaskAffinity Affinity { get { return TaskAffinity.Exclusive; } }
20+
}
21+
}

0 commit comments

Comments
 (0)