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

Commit 865bc2b

Browse files
authored
Merge pull request #567 from github/grokys/maintainer-workflow
Maintainer workflow
2 parents 6f99a4c + 5ad4d53 commit 865bc2b

File tree

53 files changed

+2707
-92
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2707
-92
lines changed

src/GitHub.App/Api/ApiClient.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,16 @@ public IObservable<Unit> DeleteApplicationAuthorization(int id, [AllowNull]strin
236236
return gitHubClient.Authorization.Delete(id, twoFactorAuthorizationCode);
237237
}
238238

239+
public IObservable<PullRequest> GetPullRequest(string owner, string name, int number)
240+
{
241+
return gitHubClient.PullRequest.Get(owner, name, number);
242+
}
243+
244+
public IObservable<PullRequestFile> GetPullRequestFiles(string owner, string name, int number)
245+
{
246+
return gitHubClient.PullRequest.Files(owner, name, number);
247+
}
248+
239249
public IObservable<PullRequest> GetPullRequestsForRepository(string owner, string name)
240250
{
241251
return gitHubClient.PullRequest.GetAllForRepository(owner, name,

src/GitHub.App/GitHub.App.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,15 @@
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>
133134
<DesignTime>True</DesignTime>
134135
<DependentUpon>Resources.resx</DependentUpon>
135136
</Compile>
136137
<Compile Include="SampleData\AccountDesigner.cs" />
138+
<Compile Include="SampleData\LocalRepositoryModelDesigner.cs" />
137139
<Compile Include="SampleData\PullRequestCreationViewModelDesigner.cs" />
138140
<Compile Include="SampleData\PullRequestDetailViewModelDesigner.cs" />
139141
<Compile Include="SampleData\LoggedOutViewModelDesigner.cs" />
@@ -204,6 +206,8 @@
204206
<Compile Include="ViewModels\LogoutRequiredViewModel.cs" />
205207
<Compile Include="ViewModels\PullRequestCreationViewModel.cs" />
206208
<Compile Include="ViewModels\PullRequestDetailViewModel.cs" />
209+
<Compile Include="ViewModels\PullRequestDirectoryNode.cs" />
210+
<Compile Include="ViewModels\PullRequestFileNode.cs" />
207211
<Compile Include="ViewModels\PullRequestListViewModel.cs" />
208212
<Compile Include="ViewModels\RepositoryCreationViewModel.cs" />
209213
<Compile Include="ViewModels\RepositoryCloneViewModel.cs" />

src/GitHub.App/Models/Account.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ public Account(Octokit.Account account)
5252
HasMaximumPrivateRepositories = OwnedPrivateRepos >= PrivateReposInPlan;
5353
}
5454

55+
public Account(Octokit.Account account, IObservable<BitmapSource> bitmapSource)
56+
: this(account)
57+
{
58+
bitmapSource.ObserveOn(RxApp.MainThreadScheduler)
59+
.Subscribe(x => Avatar = x);
60+
}
61+
5562
public bool IsOnFreePlan { get; private set; }
5663

5764
public bool HasMaximumPrivateRepositories { get; private set; }
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: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,22 @@
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
{
1111
[DebuggerDisplay("{DebuggerDisplay,nq}")]
12+
[NullGuard(ValidationFlags.None)]
1213
public sealed class PullRequestModel : NotificationAwareObject, IPullRequestModel,
1314
IEquatable<PullRequestModel>,
1415
IComparable<PullRequestModel>
1516
{
16-
public PullRequestModel(int number, string title,
17-
IAccount author, [AllowNull]IAccount assignee,
17+
public PullRequestModel(int number, string title, IAccount author,
1818
DateTimeOffset createdAt, DateTimeOffset? updatedAt = null)
1919
{
2020
Number = number;
2121
Title = title;
2222
Author = author;
23-
Assignee = assignee;
2423
CreatedAt = createdAt;
2524
UpdatedAt = updatedAt ?? CreatedAt;
2625
}
@@ -30,10 +29,10 @@ public void CopyFrom(IPullRequestModel other)
3029
if (!Equals(other))
3130
throw new ArgumentException("Instance to copy from doesn't match this instance. this:(" + this + ") other:(" + other + ")", nameof(other));
3231
Title = other.Title;
32+
State = other.State;
3333
UpdatedAt = other.UpdatedAt;
3434
CommentCount = other.CommentCount;
3535
HasNewComments = other.HasNewComments;
36-
IsOpen = other.IsOpen;
3736
Assignee = other.Assignee;
3837
}
3938

@@ -107,30 +106,60 @@ public string Title
107106
set { title = value; this.RaisePropertyChange(); }
108107
}
109108

110-
bool isOpen;
111-
public bool IsOpen
109+
PullRequestStateEnum status;
110+
public PullRequestStateEnum State
112111
{
113-
get { return isOpen; }
114-
set { isOpen = value; this.RaisePropertyChange(); }
112+
get { return status; }
113+
set
114+
{
115+
status = value;
116+
this.RaisePropertyChange();
117+
118+
// TODO: These notifications will be removed once maintainer workflow has been merged to master.
119+
this.RaisePropertyChange(nameof(IsOpen));
120+
this.RaisePropertyChange(nameof(Merged));
121+
}
115122
}
116123

124+
// TODO: Remove these property once maintainer workflow has been merged to master.
125+
public bool IsOpen => State == PullRequestStateEnum.Open;
126+
public bool Merged => State == PullRequestStateEnum.Merged;
127+
117128
int commentCount;
118129
public int CommentCount
119130
{
120131
get { return commentCount; }
121132
set { commentCount = value; this.RaisePropertyChange(); }
122133
}
123134

135+
int commitCount;
136+
public int CommitCount
137+
{
138+
get { return commitCount; }
139+
set { commitCount = value; this.RaisePropertyChange(); }
140+
}
141+
124142
bool hasNewComments;
125143
public bool HasNewComments
126144
{
127145
get { return hasNewComments; }
128146
set { hasNewComments = value; this.RaisePropertyChange(); }
129147
}
130148

149+
string body;
150+
public string Body
151+
{
152+
get { return body; }
153+
set { body = value; this.RaisePropertyChange(); }
154+
}
155+
156+
public GitReferenceModel Base { get; set; }
157+
[AllowNull]
158+
public GitReferenceModel Head { get; set; }
131159
public DateTimeOffset CreatedAt { get; set; }
132160
public DateTimeOffset UpdatedAt { get; set; }
133161
public IAccount Author { get; set; }
162+
public IReadOnlyCollection<IPullRequestFileModel> ChangedFiles { get; set; } = new IPullRequestFileModel[0];
134163

135164
IAccount assignee;
136165
[AllowNull]
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.Threading.Tasks;
4+
using GitHub.Models;
5+
using GitHub.Primitives;
6+
using GitHub.UI;
7+
using NullGuard;
8+
9+
namespace GitHub.App.SampleData
10+
{
11+
[NullGuard(ValidationFlags.None)]
12+
public class LocalRepositoryModelDesigner : ILocalRepositoryModel
13+
{
14+
public UriString CloneUrl { get; set; }
15+
public IBranch CurrentBranch { get; set; }
16+
public Octicon Icon { get; set; }
17+
public string LocalPath { get; set; }
18+
public string Name { get; set; }
19+
public string Owner { get; set; }
20+
21+
#pragma warning disable CS0067
22+
public event PropertyChangedEventHandler PropertyChanged;
23+
#pragma warning restore CS0067
24+
25+
public Task<UriString> GenerateUrl(string path = null, int startLine = -1, int endLine = -1)
26+
{
27+
throw new NotImplementedException();
28+
}
29+
30+
public void Refresh()
31+
{
32+
throw new NotImplementedException();
33+
}
34+
35+
public void SetIcon(bool isPrivate, bool isFork)
36+
{
37+
throw new NotImplementedException();
38+
}
39+
}
40+
}

src/GitHub.App/SampleData/PullRequestDetailViewModelDesigner.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
using System;
12
using System.Diagnostics.CodeAnalysis;
3+
using System.Reactive;
4+
using GitHub.Models;
25
using GitHub.ViewModels;
6+
using ReactiveUI;
37

48
namespace GitHub.SampleData
59
{
@@ -8,7 +12,68 @@ public class PullRequestDetailViewModelDesigner : BaseViewModel, IPullRequestDet
812
{
913
public PullRequestDetailViewModelDesigner()
1014
{
15+
Model = new PullRequestModel(419,
16+
"Error handling/bubbling from viewmodels to views to viewhosts",
17+
new AccountDesigner { Login = "shana", IsUser = true },
18+
DateTime.Now.Subtract(TimeSpan.FromDays(3)))
19+
{
20+
State = PullRequestStateEnum.Open,
21+
CommitCount = 9,
22+
};
1123

24+
SourceBranchDisplayName = "shana/error-handling";
25+
TargetBranchDisplayName = "master";
26+
Body = @"Adds a way to surface errors from the view model to the view so that view hosts can get to them.
27+
28+
ViewModels are responsible for handling the UI on the view they control, but they shouldn't be handling UI for things outside of the view. In this case, we're showing errors in VS outside the view, and that should be handled by the section that is hosting the view.
29+
30+
This requires that errors be propagated from the viewmodel to the view and from there to the host via the IView interface, since hosts don't usually know what they're hosting.
31+
32+
![An image](https://cloud.githubusercontent.com/assets/1174461/18882991/5dd35648-8496-11e6-8735-82c3a182e8b4.png)";
33+
34+
var gitHubDir = new PullRequestDirectoryNode("GitHub");
35+
var modelsDir = new PullRequestDirectoryNode("Models");
36+
var repositoriesDir = new PullRequestDirectoryNode("Repositories");
37+
var itrackingBranch = new PullRequestFileNode(@"GitHub\Models\ITrackingBranch.cs", PullRequestFileStatus.Modified);
38+
var oldBranchModel = new PullRequestFileNode(@"GitHub\Models\OldBranchModel.cs", PullRequestFileStatus.Removed);
39+
var concurrentRepositoryConnection = new PullRequestFileNode(@"GitHub\Repositories\ConcurrentRepositoryConnection.cs", PullRequestFileStatus.Added);
40+
41+
repositoriesDir.Files.Add(concurrentRepositoryConnection);
42+
modelsDir.Directories.Add(repositoriesDir);
43+
modelsDir.Files.Add(itrackingBranch);
44+
modelsDir.Files.Add(oldBranchModel);
45+
gitHubDir.Directories.Add(modelsDir);
46+
47+
ChangedFilesTree = new ReactiveList<IPullRequestChangeNode>();
48+
ChangedFilesTree.Add(gitHubDir);
49+
50+
ChangedFilesList = new ReactiveList<IPullRequestFileNode>();
51+
ChangedFilesList.Add(concurrentRepositoryConnection);
52+
ChangedFilesList.Add(itrackingBranch);
53+
ChangedFilesList.Add(oldBranchModel);
54+
55+
CheckoutMode = CheckoutMode.Fetch;
1256
}
57+
58+
public IPullRequestModel Model { get; }
59+
public string SourceBranchDisplayName { get; }
60+
public string TargetBranchDisplayName { get; }
61+
public string Body { get; }
62+
public ChangedFilesViewType ChangedFilesViewType { get; set; }
63+
public OpenChangedFileAction OpenChangedFileAction { get; set; }
64+
public IReactiveList<IPullRequestChangeNode> ChangedFilesTree { get; }
65+
public IReactiveList<IPullRequestFileNode> ChangedFilesList { get; }
66+
public CheckoutMode CheckoutMode { get; set; }
67+
public string CheckoutError { get; set; }
68+
public int CommitsBehind { get; set; }
69+
public string CheckoutDisabledMessage { get; set; }
70+
71+
public ReactiveCommand<Unit> Checkout { get; }
72+
public ReactiveCommand<object> OpenOnGitHub { get; }
73+
public ReactiveCommand<object> ActivateItem { get; }
74+
public ReactiveCommand<object> ToggleChangedFilesView { get; }
75+
public ReactiveCommand<object> ToggleOpenChangedFileAction { get; }
76+
public ReactiveCommand<object> OpenFile { get; }
77+
public ReactiveCommand<object> DiffFile { get; }
1378
}
1479
}

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/GitClient.cs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.ComponentModel.Composition;
34
using System.Linq;
45
using System.Reactive;
@@ -61,13 +62,33 @@ public Task Fetch(IRepository repository, string remoteName, params string[] ref
6162
});
6263
}
6364

65+
public Task Checkout(IRepository repository, string branchName)
66+
{
67+
Guard.ArgumentNotEmptyString(branchName, nameof(branchName));
68+
69+
return Task.Factory.StartNew(() =>
70+
{
71+
repository.Checkout(branchName);
72+
});
73+
}
74+
75+
public Task SetConfig(IRepository repository, string key, string value)
76+
{
77+
Guard.ArgumentNotEmptyString(key, nameof(key));
78+
Guard.ArgumentNotEmptyString(value, nameof(value));
79+
80+
return Task.Factory.StartNew(() =>
81+
{
82+
repository.Config.Set(key, value);
83+
});
84+
}
85+
6486
public Task SetRemote(IRepository repository, string remoteName, Uri url)
6587
{
6688
Guard.ArgumentNotEmptyString(remoteName, nameof(remoteName));
6789

6890
return Task.Factory.StartNew(() =>
6991
{
70-
7192
repository.Config.Set("remote." + remoteName + ".url", url.ToString());
7293
repository.Config.Set("remote." + remoteName + ".fetch", "+refs/heads/*:refs/remotes/" + remoteName + "/*");
7394
});
@@ -92,11 +113,20 @@ public Task SetTrackingBranch(IRepository repository, string branchName, string
92113
});
93114
}
94115

95-
public Task<Remote> GetHttpRemote(IRepository repo, string remote)
116+
public Task UnsetConfig(IRepository repository, string key)
96117
{
118+
Guard.ArgumentNotEmptyString(key, nameof(key));
119+
97120
return Task.Factory.StartNew(() =>
98121
{
122+
repository.Config.Unset(key);
123+
});
124+
}
99125

126+
public Task<Remote> GetHttpRemote(IRepository repo, string remote)
127+
{
128+
return Task.Factory.StartNew(() =>
129+
{
100130
var uri = GitService.GitServiceHelper.GetRemoteUri(repo, remote);
101131
var remoteName = uri.IsHypertextTransferProtocol ? remote : remote + "-http";
102132
var ret = repo.Network.Remotes[remoteName];

0 commit comments

Comments
 (0)