Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit e5aecc9

Browse files
committed
Read pull request details view ModelService.
Not yet caching it yet though.
1 parent f862a3d commit e5aecc9

22 files changed

+306
-167
lines changed

src/GitHub.App/GitHub.App.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
<Compile Include="Factories\UIFactory.cs" />
128128
<Compile Include="GlobalSuppressions.cs" />
129129
<Compile Include="Infrastructure\LoggingConfiguration.cs" />
130+
<Compile Include="Models\PullRequestFileModel.cs" />
130131
<Compile Include="Models\PullRequestModel.cs" />
131132
<Compile Include="Resources.Designer.cs">
132133
<AutoGen>True</AutoGen>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
3+
namespace GitHub.Models
4+
{
5+
public class PullRequestFileModel : IPullRequestFileModel
6+
{
7+
public PullRequestFileModel(string fileName, PullRequestFileStatus status)
8+
{
9+
FileName = fileName;
10+
Status = status;
11+
}
12+
13+
public string FileName { get; set; }
14+
public PullRequestFileStatus Status { get; set; }
15+
}
16+
}

src/GitHub.App/Models/PullRequestModel.cs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using GitHub.VisualStudio.Helpers;
55
using NullGuard;
66
using System.Diagnostics;
7-
using GitHub.SampleData;
7+
using System.Collections.Generic;
88

99
namespace GitHub.Models
1010
{
@@ -13,14 +13,12 @@ public sealed class PullRequestModel : NotificationAwareObject, IPullRequestMode
1313
IEquatable<PullRequestModel>,
1414
IComparable<PullRequestModel>
1515
{
16-
public PullRequestModel(int number, string title,
17-
IAccount author, [AllowNull]IAccount assignee,
16+
public PullRequestModel(int number, string title, IAccount author,
1817
DateTimeOffset createdAt, DateTimeOffset? updatedAt = null)
1918
{
2019
Number = number;
2120
Title = title;
2221
Author = author;
23-
Assignee = assignee;
2422
CreatedAt = createdAt;
2523
UpdatedAt = updatedAt ?? CreatedAt;
2624
}
@@ -30,10 +28,10 @@ public void CopyFrom(IPullRequestModel other)
3028
if (!Equals(other))
3129
throw new ArgumentException("Instance to copy from doesn't match this instance. this:(" + this + ") other:(" + other + ")", nameof(other));
3230
Title = other.Title;
31+
State = other.State;
3332
UpdatedAt = other.UpdatedAt;
3433
CommentCount = other.CommentCount;
3534
HasNewComments = other.HasNewComments;
36-
IsOpen = other.IsOpen;
3735
Assignee = other.Assignee;
3836
}
3937

@@ -107,31 +105,51 @@ public string Title
107105
set { title = value; this.RaisePropertyChange(); }
108106
}
109107

110-
bool isOpen;
111-
public bool IsOpen
108+
PullRequestStateEnum status;
109+
public PullRequestStateEnum State
112110
{
113-
get { return isOpen; }
114-
set { isOpen = value; this.RaisePropertyChange(); }
111+
get { return status; }
112+
set { status = value; this.RaisePropertyChange(); this.RaisePropertyChange(nameof(IsOpen)); }
115113
}
116114

115+
// TODO: Remove these property once maintainer workflow has been merged to master.
116+
public bool IsOpen => State == PullRequestStateEnum.Open;
117+
public bool Merged => State == PullRequestStateEnum.Merged;
118+
117119
int commentCount;
118120
public int CommentCount
119121
{
120122
get { return commentCount; }
121123
set { commentCount = value; this.RaisePropertyChange(); }
122124
}
123125

126+
int commitCount;
127+
public int CommitCount
128+
{
129+
get { return commitCount; }
130+
set { commitCount = value; this.RaisePropertyChange(); }
131+
}
132+
124133
bool hasNewComments;
125134
public bool HasNewComments
126135
{
127136
get { return hasNewComments; }
128137
set { hasNewComments = value; this.RaisePropertyChange(); }
129138
}
130139

140+
string body;
141+
public string Body
142+
{
143+
get { return body; }
144+
set { body = value; this.RaisePropertyChange(); }
145+
}
146+
147+
public GitReferenceModel Base { get; set; }
148+
public GitReferenceModel Head { get; set; }
131149
public DateTimeOffset CreatedAt { get; set; }
132150
public DateTimeOffset UpdatedAt { get; set; }
133-
public bool Merged { get; set; }
134151
public IAccount Author { get; set; }
152+
public IList<IPullRequestFileModel> ChangedFiles { get; set; } = new IPullRequestFileModel[0];
135153

136154
IAccount assignee;
137155
[AllowNull]

src/GitHub.App/SampleData/PullRequestDetailViewModelDesigner.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class PullRequestDetailViewModelDesigner : BaseViewModel, IPullRequestDet
1313
public PullRequestDetailViewModelDesigner()
1414
{
1515
Title = "Error handling/bubbling from viewmodels to views to viewhosts";
16-
State = new PullRequestState { Name = "Open", IsOpen = true };
16+
State = PullRequestStateEnum.Open;
1717
SourceBranchDisplayName = "shana/error-handling";
1818
TargetBranchDisplayName = "master";
1919
CommitCount = 9;
@@ -31,9 +31,9 @@ public PullRequestDetailViewModelDesigner()
3131
var gitHubDir = new PullRequestDirectoryViewModel("GitHub");
3232
var modelsDir = new PullRequestDirectoryViewModel("Models");
3333
var repositoriesDir = new PullRequestDirectoryViewModel("Repositories");
34-
var itrackingBranch = new PullRequestFileViewModel(@"GitHub\Models\ITrackingBranch.cs", false, false);
35-
var oldBranchModel = new PullRequestFileViewModel(@"GitHub\Models\OldBranchModel.cs", false, false);
36-
var concurrentRepositoryConnection = new PullRequestFileViewModel(@"GitHub\Repositories\ConcurrentRepositoryConnection.cs", false, true);
34+
var itrackingBranch = new PullRequestFileViewModel(@"GitHub\Models\ITrackingBranch.cs", PullRequestFileStatus.Modified);
35+
var oldBranchModel = new PullRequestFileViewModel(@"GitHub\Models\OldBranchModel.cs", PullRequestFileStatus.Removed);
36+
var concurrentRepositoryConnection = new PullRequestFileViewModel(@"GitHub\Repositories\ConcurrentRepositoryConnection.cs", PullRequestFileStatus.Added);
3737

3838
repositoriesDir.Files.Add(concurrentRepositoryConnection);
3939
modelsDir.Directories.Add(repositoriesDir);
@@ -53,7 +53,7 @@ public PullRequestDetailViewModelDesigner()
5353
CheckoutMode = CheckoutMode.Fetch;
5454
}
5555

56-
public PullRequestState State { get; }
56+
public PullRequestStateEnum State { get; }
5757
public string SourceBranchDisplayName { get; }
5858
public string TargetBranchDisplayName { get; }
5959
public int CommitCount { get; }

src/GitHub.App/SampleData/PullRequestListViewModelDesigner.cs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,26 @@ public PullRequestListViewModelDesigner()
2020
var prs = new TrackingCollection<IPullRequestModel>(Observable.Empty<IPullRequestModel>());
2121
prs.Add(new PullRequestModel(399, "Let's try doing this differently",
2222
new AccountDesigner { Login = "shana", IsUser = true },
23-
new AccountDesigner { Login = "shana", IsUser = true },
24-
DateTimeOffset.Now - TimeSpan.FromDays(1)));
23+
DateTimeOffset.Now - TimeSpan.FromDays(1))
24+
{
25+
Assignee = new AccountDesigner { Login = "shana", IsUser = true },
26+
});
2527
prs.Add(new PullRequestModel(389, "Build system upgrade",
26-
new AccountDesigner { Login = "haacked", IsUser = true },
2728
new AccountDesigner { Login = "shana", IsUser = true },
28-
DateTimeOffset.Now - TimeSpan.FromMinutes(2)) { CommentCount = 4, HasNewComments = false });
29+
DateTimeOffset.Now - TimeSpan.FromMinutes(2))
30+
{
31+
CommentCount = 4,
32+
HasNewComments = false,
33+
Assignee = new AccountDesigner { Login = "haacked", IsUser = true },
34+
});
2935
prs.Add(new PullRequestModel(409, "Fix publish button style and a really, really long name for this thing... OMG look how long this name is yusssss",
30-
new AccountDesigner { Login = "shana", IsUser = true },
31-
new AccountDesigner { Login = "Haacked", IsUser = true },
32-
DateTimeOffset.Now - TimeSpan.FromHours(5)) { CommentCount = 27, HasNewComments = true });
36+
new AccountDesigner { Login = "shana", IsUser = true },
37+
DateTimeOffset.Now - TimeSpan.FromHours(5))
38+
{
39+
CommentCount = 27,
40+
HasNewComments = true,
41+
Assignee = new AccountDesigner { Login = "Haacked", IsUser = true },
42+
});
3343
PullRequests = prs;
3444

3545
States = new List<PullRequestState> {

src/GitHub.App/Services/ModelService.cs

Lines changed: 93 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,23 @@ public ITrackingCollection<IPullRequestModel> GetPullRequests(ILocalRepositoryMo
177177
return collection;
178178
}
179179

180+
public IObservable<IPullRequestModel> GetPullRequest(ILocalRepositoryModel repo, int number)
181+
{
182+
var keyobs = GetUserFromCache()
183+
.Select(user => string.Format(CultureInfo.InvariantCulture, "{0}|{1}:{2}", CacheIndex.PRPrefix, user.Login, repo.Name));
184+
185+
return Observable.Defer(() =>
186+
{
187+
// TODO: This needs to go via the cache.
188+
return Observable.CombineLatest(
189+
apiClient.GetPullRequest(repo.CloneUrl.Owner, repo.CloneUrl.RepositoryName, number),
190+
apiClient.GetPullRequestFiles(repo.CloneUrl.Owner, repo.CloneUrl.RepositoryName, number).ToList(),
191+
(pr, files) => new { PullRequest = pr, Files = files })
192+
.Select(x => PullRequestCacheItem.Create(x.PullRequest, x.Files))
193+
.Select(Create);
194+
});
195+
}
196+
180197
public ITrackingCollection<IRemoteRepositoryModel> GetRepositories(ITrackingCollection<IRemoteRepositoryModel> collection)
181198
{
182199
var keyobs = GetUserFromCache()
@@ -343,13 +360,20 @@ IPullRequestModel Create(PullRequestCacheItem prCacheItem)
343360
prCacheItem.Number,
344361
prCacheItem.Title,
345362
Create(prCacheItem.Author),
346-
prCacheItem.Assignee != null ? Create(prCacheItem.Assignee) : null,
347363
prCacheItem.CreatedAt,
348364
prCacheItem.UpdatedAt)
349365
{
366+
Assignee = prCacheItem.Assignee != null ? Create(prCacheItem.Assignee) : null,
367+
Base = prCacheItem.Base,
368+
Body = prCacheItem.Body,
369+
ChangedFiles = prCacheItem.ChangedFiles.Select(x => (IPullRequestFileModel)new PullRequestFileModel(x.FileName, x.Status)).ToList(),
350370
CommentCount = prCacheItem.CommentCount,
351-
IsOpen = prCacheItem.IsOpen,
352-
Merged = prCacheItem.Merged,
371+
CommitCount = prCacheItem.CommitCount,
372+
CreatedAt = prCacheItem.CreatedAt,
373+
Head = prCacheItem.Head,
374+
State = prCacheItem.State.HasValue ?
375+
prCacheItem.State.Value :
376+
prCacheItem.IsOpen.Value ? PullRequestStateEnum.Open : PullRequestStateEnum.Closed,
353377
};
354378
}
355379

@@ -427,41 +451,98 @@ public AccountCacheItem Owner
427451
public DateTimeOffset UpdatedAt { get; set; }
428452
}
429453

454+
[NullGuard(ValidationFlags.None)]
430455
public class PullRequestCacheItem : CacheItem
431456
{
432457
public static PullRequestCacheItem Create(PullRequest pr)
433458
{
434-
return new PullRequestCacheItem(pr);
459+
return new PullRequestCacheItem(pr, new PullRequestFile[0]);
460+
}
461+
462+
public static PullRequestCacheItem Create(PullRequest pr, IList<PullRequestFile> files)
463+
{
464+
return new PullRequestCacheItem(pr, files);
435465
}
436466

437467
public PullRequestCacheItem() {}
468+
438469
public PullRequestCacheItem(PullRequest pr)
470+
: this(pr, new PullRequestFile[0])
471+
{
472+
}
473+
474+
public PullRequestCacheItem(PullRequest pr, IList<PullRequestFile> files)
439475
{
440476
Title = pr.Title;
441477
Number = pr.Number;
478+
Base = new GitReferenceModel { Label = pr.Base.Label, Ref = pr.Base.Ref, RepositoryCloneUrl = pr.Base.Repository.CloneUrl };
479+
Head = new GitReferenceModel { Label = pr.Head.Label, Ref = pr.Head.Ref, RepositoryCloneUrl = pr.Head.Repository.CloneUrl };
442480
CommentCount = pr.Comments + pr.ReviewComments;
481+
CommitCount = pr.Commits;
443482
Author = new AccountCacheItem(pr.User);
444483
Assignee = pr.Assignee != null ? new AccountCacheItem(pr.Assignee) : null;
445484
CreatedAt = pr.CreatedAt;
446485
UpdatedAt = pr.UpdatedAt;
486+
Body = pr.Body;
487+
ChangedFiles = files.Select(x => new PullRequestFileCacheItem(x)).ToList();
488+
State = GetState(pr);
447489
IsOpen = pr.State == ItemState.Open;
448490
Merged = pr.Merged;
449491
Key = Number.ToString(CultureInfo.InvariantCulture);
450492
Timestamp = UpdatedAt;
451493
}
452494

453-
[AllowNull]
454-
public string Title {[return: AllowNull] get; set; }
495+
public string Title {get; set; }
455496
public int Number { get; set; }
497+
public GitReferenceModel Base { get; set; }
498+
public GitReferenceModel Head { get; set; }
456499
public int CommentCount { get; set; }
457-
[AllowNull]
458-
public AccountCacheItem Author {[return: AllowNull] get; set; }
459-
[AllowNull]
460-
public AccountCacheItem Assignee { [return: AllowNull] get; set; }
500+
public int CommitCount { get; set; }
501+
public AccountCacheItem Author { get; set; }
502+
public AccountCacheItem Assignee { get; set; }
461503
public DateTimeOffset CreatedAt { get; set; }
462504
public DateTimeOffset UpdatedAt { get; set; }
463-
public bool IsOpen { get; set; }
464-
public bool Merged { get; set; }
505+
public string Body { get; set; }
506+
public IList<PullRequestFileCacheItem> ChangedFiles { get; set; } = new PullRequestFileCacheItem[0];
507+
508+
// Nullable for compatibility with old caches.
509+
public PullRequestStateEnum? State { get; set; }
510+
511+
// This fields exists only for compatibility with old caches. The State property should be used.
512+
public bool? IsOpen { get; set; }
513+
public bool? Merged { get; set; }
514+
515+
static PullRequestStateEnum GetState(PullRequest pullRequest)
516+
{
517+
if (pullRequest.State == ItemState.Open)
518+
{
519+
return PullRequestStateEnum.Open;
520+
}
521+
else if (pullRequest.Merged)
522+
{
523+
return PullRequestStateEnum.Merged;
524+
}
525+
else
526+
{
527+
return PullRequestStateEnum.Closed;
528+
}
529+
}
530+
}
531+
532+
public class PullRequestFileCacheItem
533+
{
534+
public PullRequestFileCacheItem()
535+
{
536+
}
537+
538+
public PullRequestFileCacheItem(PullRequestFile file)
539+
{
540+
FileName = file.FileName;
541+
Status = (PullRequestFileStatus)Enum.Parse(typeof(PullRequestFileStatus), file.Status, true);
542+
}
543+
544+
public string FileName { get; set; }
545+
public PullRequestFileStatus Status { get; set; }
465546
}
466547
}
467548
}

src/GitHub.App/Services/PullRequestService.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public IObservable<HistoryDivergence> CalculateHistoryDivergence(ILocalRepositor
147147
});
148148
}
149149

150-
public IObservable<IBranch> GetLocalBranches(ILocalRepositoryModel repository, PullRequest pullRequest)
150+
public IObservable<IBranch> GetLocalBranches(ILocalRepositoryModel repository, IPullRequestModel pullRequest)
151151
{
152152
return Observable.Defer(() =>
153153
{
@@ -157,13 +157,12 @@ public IObservable<IBranch> GetLocalBranches(ILocalRepositoryModel repository, P
157157
});
158158
}
159159

160-
public bool IsPullRequestFromFork(ILocalRepositoryModel repository, PullRequest pullRequest)
160+
public bool IsPullRequestFromFork(ILocalRepositoryModel repository, IPullRequestModel pullRequest)
161161
{
162-
var sourceUrl = new UriString(pullRequest.Head.Repository.CloneUrl);
163-
return sourceUrl.ToRepositoryUrl() != repository.CloneUrl.ToRepositoryUrl();
162+
return pullRequest.Head.RepositoryCloneUrl.ToRepositoryUrl() != repository.CloneUrl.ToRepositoryUrl();
164163
}
165164

166-
public IObservable<Unit> SwitchToBranch(ILocalRepositoryModel repository, PullRequest pullRequest)
165+
public IObservable<Unit> SwitchToBranch(ILocalRepositoryModel repository, IPullRequestModel pullRequest)
167166
{
168167
return Observable.Defer(async () =>
169168
{
@@ -219,7 +218,7 @@ async Task DoFetchAndCheckout(ILocalRepositoryModel repository, int pullRequestN
219218
IEnumerable<string> GetLocalBranchesInternal(
220219
ILocalRepositoryModel localRepository,
221220
IRepository repository,
222-
PullRequest pullRequest)
221+
IPullRequestModel pullRequest)
223222
{
224223
if (!IsPullRequestFromFork(localRepository, pullRequest))
225224
{

0 commit comments

Comments
 (0)