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

Commit 191152a

Browse files
authored
Merge branch 'master' into paladique/update-manifest
2 parents 553ec00 + 53995e8 commit 191152a

File tree

10 files changed

+186
-43
lines changed

10 files changed

+186
-43
lines changed

src/GitHub.App/Services/GitClient.cs

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using System.Reactive;
55
using System.Reactive.Linq;
6+
using System.Threading.Tasks;
67
using GitHub.Extensions;
78
using GitHub.Primitives;
89
using LibGit2Sharp;
@@ -23,65 +24,61 @@ public GitClient(IGitHubCredentialProvider credentialProvider)
2324
fetchOptions = new FetchOptions { CredentialsProvider = credentialProvider.HandleCredentials };
2425
}
2526

26-
public IObservable<Unit> Push(IRepository repository, string branchName, string remoteName)
27+
public Task Push(IRepository repository, string branchName, string remoteName)
2728
{
2829
Guard.ArgumentNotEmptyString(branchName, nameof(branchName));
2930
Guard.ArgumentNotEmptyString(remoteName, nameof(remoteName));
3031

31-
return Observable.Defer(() =>
32+
return Task.Factory.StartNew(() =>
3233
{
3334
if (repository.Head?.Commits != null && repository.Head.Commits.Any())
3435
{
3536
var remote = repository.Network.Remotes[remoteName];
3637
repository.Network.Push(remote, "HEAD", @"refs/heads/" + branchName, pushOptions);
3738
}
38-
return Observable.Return(Unit.Default);
3939
});
4040
}
4141

42-
public IObservable<Unit> Fetch(IRepository repository, string remoteName)
42+
public Task Fetch(IRepository repository, string remoteName)
4343
{
4444
Guard.ArgumentNotEmptyString(remoteName, nameof(remoteName));
4545

46-
return Observable.Defer(() =>
46+
return Task.Factory.StartNew(() =>
4747
{
4848
var remote = repository.Network.Remotes[remoteName];
4949
repository.Network.Fetch(remote, fetchOptions);
50-
return Observable.Return(Unit.Default);
5150
});
5251
}
5352

54-
public IObservable<Unit> Fetch(IRepository repository, string remoteName, params string[] refspecs)
53+
public Task Fetch(IRepository repository, string remoteName, params string[] refspecs)
5554
{
5655
Guard.ArgumentNotEmptyString(remoteName, nameof(remoteName));
5756

58-
return Observable.Defer(() =>
57+
return Task.Factory.StartNew(() =>
5958
{
6059
var remote = repository.Network.Remotes[remoteName];
6160
repository.Network.Fetch(remote, refspecs, fetchOptions);
62-
return Observable.Return(Unit.Default);
6361
});
6462
}
6563

66-
public IObservable<Unit> SetRemote(IRepository repository, string remoteName, Uri url)
64+
public Task SetRemote(IRepository repository, string remoteName, Uri url)
6765
{
6866
Guard.ArgumentNotEmptyString(remoteName, nameof(remoteName));
6967

70-
return Observable.Defer(() =>
68+
return Task.Factory.StartNew(() =>
7169
{
70+
7271
repository.Config.Set("remote." + remoteName + ".url", url.ToString());
7372
repository.Config.Set("remote." + remoteName + ".fetch", "+refs/heads/*:refs/remotes/" + remoteName + "/*");
74-
75-
return Observable.Return(Unit.Default);
7673
});
7774
}
7875

79-
public IObservable<Unit> SetTrackingBranch(IRepository repository, string branchName, string remoteName)
76+
public Task SetTrackingBranch(IRepository repository, string branchName, string remoteName)
8077
{
8178
Guard.ArgumentNotEmptyString(branchName, nameof(branchName));
8279
Guard.ArgumentNotEmptyString(remoteName, nameof(remoteName));
8380

84-
return Observable.Defer(() =>
81+
return Task.Factory.StartNew(() =>
8582
{
8683
var remoteBranchName = IsCanonical(remoteName) ? remoteName : "refs/remotes/" + remoteName + "/" + branchName;
8784
var remoteBranch = repository.Branches[remoteBranchName];
@@ -92,21 +89,21 @@ public IObservable<Unit> SetTrackingBranch(IRepository repository, string branch
9289
var localBranch = repository.Branches[localBranchName];
9390
repository.Branches.Update(localBranch, b => b.TrackedBranch = remoteBranch.CanonicalName);
9491
}
95-
return Observable.Return(Unit.Default);
9692
});
9793
}
9894

99-
public IObservable<Remote> GetHttpRemote(IRepository repo, string remote)
95+
public Task<Remote> GetHttpRemote(IRepository repo, string remote)
10096
{
101-
return Observable.Defer(() => Observable.Return(GitService.GitServiceHelper.GetRemoteUri(repo, remote)))
102-
.Select(uri => new { Remote = uri.IsHypertextTransferProtocol ? remote : remote + "-http", Uri = uri })
103-
.Select(r =>
104-
{
105-
var ret = repo.Network.Remotes[r.Remote];
106-
if (ret == null)
107-
ret = repo.Network.Remotes.Add(r.Remote, UriString.ToUriString(r.Uri.ToRepositoryUrl()));
108-
return ret;
109-
});
97+
return Task.Factory.StartNew(() =>
98+
{
99+
100+
var uri = GitService.GitServiceHelper.GetRemoteUri(repo, remote);
101+
var remoteName = uri.IsHypertextTransferProtocol ? remote : remote + "-http";
102+
var ret = repo.Network.Remotes[remoteName];
103+
if (ret == null)
104+
ret = repo.Network.Remotes.Add(remoteName, UriString.ToUriString(uri.ToRepositoryUrl()));
105+
return ret;
106+
});
110107
}
111108

112109
static bool IsCanonical(string s)

src/GitHub.App/Services/RepositoryPublishService.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.ComponentModel.Composition;
33
using System.IO;
44
using System.Reactive.Linq;
5+
using System.Reactive.Threading.Tasks;
56
using GitHub.Api;
67
using GitHub.Models;
78
using LibGit2Sharp;
@@ -38,11 +39,16 @@ public string LocalRepositoryName
3839
IApiClient apiClient)
3940
{
4041
return Observable.Defer(() => apiClient.CreateRepository(newRepository, account.Login, account.IsUser)
41-
.Select(remoteRepo => new { RemoteRepo = remoteRepo, LocalRepo = activeRepository }))
42-
.SelectMany(repo => gitClient.SetRemote(repo.LocalRepo, "origin", new Uri(repo.RemoteRepo.CloneUrl)).Select(_ => repo))
43-
.SelectMany(repo => gitClient.Push(repo.LocalRepo, "master", "origin").Select(_ => repo))
44-
.SelectMany(repo => gitClient.Fetch(repo.LocalRepo, "origin").Select(_ => repo))
45-
.SelectMany(repo => gitClient.SetTrackingBranch(repo.LocalRepo, "master", "origin").Select(_ => repo.RemoteRepo));
42+
.Select(remoteRepo => new { RemoteRepo = remoteRepo, LocalRepo = activeRepository }))
43+
.Select(async repo =>
44+
{
45+
await gitClient.SetRemote(repo.LocalRepo, "origin", new Uri(repo.RemoteRepo.CloneUrl));
46+
await gitClient.Push(repo.LocalRepo, "master", "origin");
47+
await gitClient.Fetch(repo.LocalRepo, "origin");
48+
await gitClient.SetTrackingBranch(repo.LocalRepo, "master", "origin");
49+
return repo.RemoteRepo;
50+
})
51+
.Select(t => t.Result);
4652
}
4753
}
4854
}

src/GitHub.Exports.Reactive/Services/IGitClient.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using System;
2-
using System.Reactive;
2+
using System.Threading.Tasks;
33
using LibGit2Sharp;
44

55
namespace GitHub.Services
@@ -13,15 +13,15 @@ public interface IGitClient
1313
/// <param name="remoteName">The name of the remote</param>
1414
/// <param name="branchName">the branch to pull</param>
1515
/// <returns></returns>
16-
IObservable<Unit> Push(IRepository repository, string branchName, string remoteName);
16+
Task Push(IRepository repository, string branchName, string remoteName);
1717

1818
/// <summary>
1919
/// Fetches the remote.
2020
/// </summary>
2121
/// <param name="repository">The repository to pull</param>
2222
/// <param name="remoteName">The name of the remote</param>
2323
/// <returns></returns>
24-
IObservable<Unit> Fetch(IRepository repository, string remoteName);
24+
Task Fetch(IRepository repository, string remoteName);
2525

2626
/// <summary>
2727
/// Fetches from the remote, using custom refspecs.
@@ -30,7 +30,7 @@ public interface IGitClient
3030
/// <param name="remoteName">The name of the remote</param>
3131
/// <param name="refspecs">The custom refspecs</param>
3232
/// <returns></returns>
33-
IObservable<Unit> Fetch(IRepository repository, string remoteName, params string[] refspecs);
33+
Task Fetch(IRepository repository, string remoteName, params string[] refspecs);
3434

3535
/// <summary>
3636
/// Sets the specified remote to the specified URL.
@@ -39,7 +39,7 @@ public interface IGitClient
3939
/// <param name="remoteName">The name of the remote</param>
4040
/// <param name="url">The URL to set as the remote</param>
4141
/// <returns></returns>
42-
IObservable<Unit> SetRemote(IRepository repository, string remoteName, Uri url);
42+
Task SetRemote(IRepository repository, string remoteName, Uri url);
4343

4444
/// <summary>
4545
/// Sets the remote branch that the local branch tracks
@@ -48,8 +48,8 @@ public interface IGitClient
4848
/// <param name="branchName">The name of the local remote</param>
4949
/// <param name="remoteName">The name of the remote branch</param>
5050
/// <returns></returns>
51-
IObservable<Unit> SetTrackingBranch(IRepository repository, string branchName, string remoteName);
51+
Task SetTrackingBranch(IRepository repository, string branchName, string remoteName);
5252

53-
IObservable<Remote> GetHttpRemote(IRepository repo, string remote);
53+
Task<Remote> GetHttpRemote(IRepository repo, string remote);
5454
}
5555
}

src/GitHub.VisualStudio/PkgCmdID.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// MUST match PkgCmdID.h
33
namespace GitHub.VisualStudio
44
{
5-
static class PkgCmdIDList
5+
public static class PkgCmdIDList
66
{
77
public const int addConnectionCommand = 0x110;
88
public const int idGitHubToolbar = 0x1120;

src/GitHub.VisualStudio/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33

44
[assembly: AssemblyTitle("GitHub.VisualStudio")]
55
[assembly: AssemblyDescription("GitHub for Visual Studio VSPackage")]
6-
[assembly: Guid("fad77eaa-3fe1-4c4b-88dc-3753b6263cd7")]
6+
[assembly: Guid("fad77eaa-3fe1-4c4b-88dc-3753b6263cd7")]

src/GitHub.VisualStudio/UI/Views/GitHubPaneViewModel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ void StartFlow(UIControllerFlow controllerFlow, [AllowNull]IConnection conn, Vie
279279
void GoForward(ViewWithData data)
280280
{
281281
currentNavItem++;
282-
if (currentNavItem < navStack.Count - 1)
283-
navStack.RemoveRange(currentNavItem, navStack.Count - 1 - currentNavItem);
282+
if (currentNavItem < navStack.Count)
283+
navStack.RemoveRange(currentNavItem, navStack.Count - currentNavItem);
284284
navStack.Add(data);
285285
}
286286

src/UnitTests/GitHub.App/ViewModels/PullRequestCreationViewModelTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ static LibGit2Sharp.IRepository SetupLocalRepoMock(IGitClient gitClient, IGitSer
2323
{
2424
var l2remote = Substitute.For<LibGit2Sharp.Remote>();
2525
l2remote.Name.Returns(remote);
26-
gitClient.GetHttpRemote(Args.LibGit2Repo, Args.String).Returns(Observable.Return(l2remote));
26+
gitClient.GetHttpRemote(Args.LibGit2Repo, Args.String).Returns(Task.FromResult(l2remote));
2727

2828
var l2repo = Substitute.For<LibGit2Sharp.IRepository>();
2929
var l2branchcol = Substitute.For<LibGit2Sharp.BranchCollection>();
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
using GitHub.Api;
2+
using GitHub.Exports;
3+
using GitHub.Models;
4+
using GitHub.Primitives;
5+
using GitHub.Services;
6+
using GitHub.UI;
7+
using GitHub.VisualStudio;
8+
using GitHub.VisualStudio.UI.Views;
9+
using NSubstitute;
10+
using System;
11+
using System.Collections.Generic;
12+
using System.Collections.ObjectModel;
13+
using System.ComponentModel.Composition;
14+
using System.ComponentModel.Design;
15+
using System.Linq;
16+
using System.Reactive.Linq;
17+
using UnitTests;
18+
using Xunit;
19+
20+
public class GitHubPaneViewModelTests : TestBaseClass
21+
{
22+
readonly IServiceProvider serviceProvider;
23+
readonly IUIController uiController;
24+
readonly FakeMenuCommandService menuCommandService;
25+
readonly GitHubPaneViewModel viewModel;
26+
UIViewType lastUiControllerJump;
27+
28+
public GitHubPaneViewModelTests()
29+
{
30+
var repositoryHosts = Substitutes.RepositoryHosts;
31+
repositoryHosts.IsLoggedInToAnyHost.Returns(true);
32+
33+
var teamExplorerServiceHolder = Substitute.For<ITeamExplorerServiceHolder>();
34+
var activeRepo = Substitute.For<ILocalRepositoryModel>();
35+
activeRepo.CloneUrl.Returns(new UriString("https://github.com/foo/foo"));
36+
teamExplorerServiceHolder
37+
.When(x => x.Subscribe(Arg.Any<object>(), Arg.Any<Action<ILocalRepositoryModel>>()))
38+
.Do(x =>
39+
{
40+
var invokeAction = x.Arg<Action<ILocalRepositoryModel>>();
41+
invokeAction(activeRepo);
42+
});
43+
44+
var connectionManager = Substitutes.ConnectionManager;
45+
var connection = Substitutes.Connection;
46+
var connectionHostAddress = HostAddress.Create(activeRepo.CloneUrl.ToString());
47+
connection.HostAddress.Returns(connectionHostAddress);
48+
connectionManager.Connections.Returns(new ObservableCollection<IConnection>(new[] {
49+
connection
50+
}));
51+
connection.Login().Returns(Observable.Return(connection));
52+
53+
var host = Substitute.For<IRepositoryHost>();
54+
host.IsLoggedIn.Returns(true);
55+
repositoryHosts.LookupHost(connectionHostAddress).Returns(host);
56+
57+
serviceProvider = Substitutes.GetFullyMockedServiceProvider();
58+
menuCommandService = new FakeMenuCommandService();
59+
serviceProvider.GetService(typeof(IMenuCommandService)).Returns(menuCommandService);
60+
61+
var uiProvider = serviceProvider as IUIProvider;
62+
uiProvider.TryGetService(typeof(IUIProvider)).Returns(serviceProvider);
63+
64+
uiController = Substitute.For<IUIController>();
65+
uiController.CurrentFlow.Returns(UIControllerFlow.PullRequests);
66+
uiController.SelectedFlow.Returns(UIControllerFlow.PullRequests);
67+
uiController
68+
.When(x => x.Jump(Arg.Any<ViewWithData>()))
69+
.Do(x => lastUiControllerJump = x.Arg<ViewWithData>().ViewType);
70+
71+
var exportFactoryProvider = Substitutes.ExportFactoryProvider;
72+
uiProvider.TryGetService(typeof(IExportFactoryProvider)).Returns(exportFactoryProvider);
73+
exportFactoryProvider.UIControllerFactory.Returns(new ExportFactory<IUIController>(
74+
() => Tuple.Create<IUIController, Action>(uiController, () => { })));
75+
76+
viewModel = new GitHubPaneViewModel(
77+
Substitute.For<ISimpleApiClientFactory>(),
78+
teamExplorerServiceHolder,
79+
connectionManager,
80+
repositoryHosts,
81+
Substitute.For<INotificationDispatcher>());
82+
83+
viewModel.ActiveRepo = activeRepo;
84+
}
85+
86+
[Fact]
87+
public void ListRefreshKeepsListVisible_DoesNotSwitchToPRCreation()
88+
{
89+
RunSteps(new[]
90+
{
91+
new NavStep(LoadDirection.Forward, UIViewType.PRList),
92+
new NavStep(LoadDirection.Forward, UIViewType.PRCreation),
93+
new NavStep(LoadDirection.Back, UIViewType.PRList),
94+
new NavStep(LoadDirection.Forward, UIViewType.PRCreation),
95+
new NavStep(LoadDirection.Forward, UIViewType.PRList),
96+
});
97+
98+
menuCommandService.ExecuteCommand(PkgCmdIDList.refreshCommand);
99+
100+
Assert.Equal(UIViewType.PRList, lastUiControllerJump);
101+
}
102+
103+
private void RunSteps(IEnumerable<NavStep> steps)
104+
{
105+
var observableSteps = steps
106+
.Select(x => new LoadData
107+
{
108+
Direction = x.Direction,
109+
Data = new ViewWithData() { ViewType = x.ViewType },
110+
View = Substitute.For<IView>()
111+
})
112+
.ToObservable();
113+
114+
uiController.SelectFlow(UIControllerFlow.PullRequests).Returns(observableSteps);
115+
116+
viewModel.Initialize(serviceProvider);
117+
}
118+
119+
private class NavStep
120+
{
121+
public NavStep(LoadDirection direction, UIViewType viewtype)
122+
{
123+
Direction = direction;
124+
ViewType = viewtype;
125+
}
126+
127+
public LoadDirection Direction { get; private set; }
128+
public UIViewType ViewType { get; private set; }
129+
}
130+
}

src/UnitTests/TestDoubles/FakeMenuCommandService.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ public void AddCommand(MenuCommand command)
1717
addedCommands.Add(command);
1818
}
1919

20+
public void ExecuteCommand(int commandId)
21+
{
22+
var command = addedCommands.Find(_ => _.CommandID.ID == commandId);
23+
if (command != null)
24+
{
25+
command.Invoke();
26+
}
27+
}
28+
2029
public void AddVerb(DesignerVerb verb)
2130
{
2231
throw new NotImplementedException();

src/UnitTests/UnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@
190190
<Compile Include="GitHub.VisualStudio\Services\ConnectionManagerTests.cs" />
191191
<Compile Include="GitHub.VisualStudio\Services\RepositoryPublishServiceTests.cs" />
192192
<Compile Include="GitHub.VisualStudio\TeamExplorer\Home\GraphsNavigationItemTests.cs" />
193+
<Compile Include="GitHub.VisualStudio\UI\Views\GitHubPaneViewModelTests.cs" />
193194
<Compile Include="GitHubPackageTests.cs" />
194195
<Compile Include="Helpers\CommandTestHelpers.cs" />
195196
<Compile Include="Helpers\LazySubstitute.cs" />

0 commit comments

Comments
 (0)