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

Commit 155aae0

Browse files
committed
Merge pull request #135 from github/feature/login-on-sync-page
Login in the sync page
2 parents 6b84fae + 11043ad commit 155aae0

File tree

12 files changed

+166
-39
lines changed

12 files changed

+166
-39
lines changed

src/GitHub.Api/SimpleApiClient.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using GitHub.Primitives;
66
using GitHub.Services;
77
using Octokit;
8+
using GitHub.Extensions;
89

910
namespace GitHub.Api
1011
{
@@ -23,10 +24,13 @@ public class SimpleApiClient : ISimpleApiClient
2324
bool? isEnterprise;
2425
bool? hasWiki;
2526

26-
public SimpleApiClient(HostAddress hostAddress, UriString repoUrl, IGitHubClient githubClient,
27+
public SimpleApiClient(UriString repoUrl, IGitHubClient githubClient,
2728
Lazy<IEnterpriseProbeTask> enterpriseProbe, Lazy<IWikiProbe> wikiProbe)
2829
{
29-
HostAddress = hostAddress;
30+
Guard.ArgumentNotNull(repoUrl, nameof(repoUrl));
31+
Guard.ArgumentNotNull(githubClient, nameof(githubClient));
32+
33+
HostAddress = HostAddress.Create(repoUrl);
3034
OriginalUrl = repoUrl;
3135
client = githubClient;
3236
this.enterpriseProbe = enterpriseProbe;
@@ -48,7 +52,7 @@ async Task<Repository> GetRepositoryInternal()
4852
await sem.WaitAsync();
4953
try
5054
{
51-
if (owner == null && OriginalUrl != null)
55+
if (owner == null)
5256
{
5357
var ownerLogin = OriginalUrl.Owner;
5458
var repositoryName = OriginalUrl.RepositoryName;
@@ -66,7 +70,12 @@ async Task<Repository> GetRepositoryInternal()
6670
}
6771
}
6872
}
69-
// it'll throw if it's private
73+
// it'll throw if it's private or an enterprise instance requiring authentication
74+
catch (ApiException)
75+
{
76+
if (!HostAddress.IsGitHubDotComUri(OriginalUrl.ToRepositoryUrl()))
77+
isEnterprise = true;
78+
}
7079
catch {}
7180
finally
7281
{

src/GitHub.Api/SimpleApiClientFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public SimpleApiClientFactory(IProgram program, Lazy<IEnterpriseProbeTask> enter
3030
public ISimpleApiClient Create(UriString repositoryUrl)
3131
{
3232
var hostAddress = HostAddress.Create(repositoryUrl);
33-
return cache.GetOrAdd(repositoryUrl, new SimpleApiClient(hostAddress, repositoryUrl,
33+
return cache.GetOrAdd(repositoryUrl, new SimpleApiClient(repositoryUrl,
3434
new GitHubClient(productHeader, new SimpleCredentialStore(hostAddress), hostAddress.ApiUri),
3535
lazyEnterpriseProbe, lazyWikiProbe));
3636
}

src/GitHub.Exports.Reactive/Extensions/ConnectionManagerExtensions.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using GitHub.Models;
33
using System;
44
using ReactiveUI;
5+
using GitHub.Primitives;
56

67
namespace GitHub.Extensions
78
{
@@ -11,7 +12,17 @@ public static IObservable<bool> IsLoggedIn(this IConnectionManager cm, IReposito
1112
{
1213
return cm.Connections.ToObservable()
1314
.SelectMany(c => c.Login())
14-
.Select(c => hosts.LookupHost(c.HostAddress)).Any(h => h.IsLoggedIn);
15+
.Select(c => hosts.LookupHost(c.HostAddress))
16+
.Any(h => h.IsLoggedIn);
17+
}
18+
19+
public static IObservable<bool> IsLoggedIn(this IConnectionManager cm, IRepositoryHosts hosts, HostAddress address)
20+
{
21+
return cm.Connections.ToObservable()
22+
.Where(c => c.HostAddress.Equals(address))
23+
.SelectMany(c => c.Login())
24+
.Select(c => hosts.LookupHost(c.HostAddress))
25+
.Any(h => h.IsLoggedIn);
1526
}
1627
}
1728
}

src/GitHub.Extensions/Guard.cs

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System;
1+
using NullGuard;
2+
using System;
23
using System.Collections.Generic;
34
using System.Diagnostics;
45
using System.Globalization;
@@ -8,6 +9,19 @@ namespace GitHub.Extensions
89
{
910
public static class Guard
1011
{
12+
public static void ArgumentNotNull([AllowNull]object value, string name)
13+
{
14+
if (value != null) return;
15+
string message = String.Format(CultureInfo.InvariantCulture, "Failed Null Check on '{0}'", name);
16+
#if DEBUG
17+
if (!InUnitTestRunner())
18+
{
19+
Debug.Fail(message);
20+
}
21+
#endif
22+
throw new ArgumentNullException(name, message);
23+
}
24+
1125
public static void ArgumentNonNegative(int value, string name)
1226
{
1327
if (value > -1) return;
@@ -78,29 +92,7 @@ public static void ArgumentInRange(int value, int minValue, int maxValue, string
7892
// Borrowed from Splat.
7993
static bool InUnitTestRunner()
8094
{
81-
var testAssemblies = new[] {
82-
"CSUNIT",
83-
"NUNIT",
84-
"XUNIT",
85-
"MBUNIT",
86-
"PEX.",
87-
"NBEHAVE",
88-
};
89-
90-
try
91-
{
92-
return SearchForAssembly(testAssemblies);
93-
}
94-
catch (Exception)
95-
{
96-
return false;
97-
}
98-
}
99-
100-
static bool SearchForAssembly(IEnumerable<string> assemblyList)
101-
{
102-
return AppDomain.CurrentDomain.GetAssemblies()
103-
.Any(x => assemblyList.Any(name => x.FullName.ToUpperInvariant().Contains(name)));
95+
return Splat.ModeDetector.InUnitTestRunner();
10496
}
10597
}
10698
}

src/GitHub.Extensions/TaskExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,8 @@ public static async Task<T> Catch<T>(this Task<T> source, Func<Exception, T> han
2020
return default(T);
2121
}
2222
}
23+
public static void Forget(this Task task)
24+
{
25+
}
2326
}
2427
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System;
2+
using System.Reactive.Linq;
3+
using GitHub.Api;
4+
using GitHub.Extensions;
5+
using GitHub.Models;
6+
using GitHub.Services;
7+
using GitHub.UI;
8+
using GitHub.VisualStudio.Base;
9+
using Microsoft.TeamFoundation.MVVM;
10+
using System.Globalization;
11+
using GitHub.Primitives;
12+
using System.Threading.Tasks;
13+
14+
namespace GitHub.VisualStudio.TeamExplorer.Sync
15+
{
16+
public class EnsureLoggedInSection : TeamExplorerSectionBase
17+
{
18+
readonly IRepositoryHosts hosts;
19+
readonly IVSServices vsServices;
20+
21+
public EnsureLoggedInSection(ISimpleApiClientFactory apiFactory, ITeamExplorerServiceHolder holder,
22+
IConnectionManager cm, IRepositoryHosts hosts, IVSServices vsServices)
23+
: base(apiFactory, holder, cm)
24+
{
25+
IsVisible = false;
26+
this.hosts = hosts;
27+
this.vsServices = vsServices;
28+
}
29+
30+
public override void Initialize(IServiceProvider serviceProvider)
31+
{
32+
base.Initialize(serviceProvider);
33+
CheckLogin().Forget();
34+
}
35+
36+
protected override void RepoChanged()
37+
{
38+
base.RepoChanged();
39+
CheckLogin().Forget();
40+
}
41+
42+
async Task CheckLogin()
43+
{
44+
// this is not a github repo, or it hasn't been published yet
45+
if (ActiveRepo == null || ActiveRepoUri == null)
46+
return;
47+
48+
var isgithub = await IsAGitHubRepo();
49+
if (!isgithub)
50+
return;
51+
52+
vsServices.ClearNotifications();
53+
var add = HostAddress.Create(ActiveRepoUri);
54+
bool loggedIn = await connectionManager.IsLoggedIn(hosts, add);
55+
if (!loggedIn)
56+
{
57+
var msg = string.Format(CultureInfo.CurrentUICulture, Resources.NotLoggedInMessage, add.Title, add.Title);
58+
vsServices.ShowMessage(
59+
msg,
60+
new RelayCommand(() => StartFlow(UIControllerFlow.Authentication))
61+
);
62+
}
63+
}
64+
65+
void StartFlow(UIControllerFlow controllerFlow)
66+
{
67+
var uiProvider = ServiceProvider.GetExportedValue<IUIProvider>();
68+
var ret = uiProvider.SetupUI(controllerFlow, null);
69+
ret.Subscribe(c => { }, () => CheckLogin().Forget());
70+
uiProvider.RunUI();
71+
}
72+
}
73+
}

src/GitHub.VisualStudio/Base/TeamExplorerItemBase.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,13 @@ protected async Task<bool> IsAGitHubRepo()
7272

7373
SimpleApiClient = apiFactory.Create(uri);
7474

75-
if (!HostAddress.IsGitHubDotComUri(uri.ToRepositoryUrl()))
75+
var isdotcom = HostAddress.IsGitHubDotComUri(uri.ToRepositoryUrl());
76+
if (!isdotcom)
7677
{
7778
var repo = await SimpleApiClient.GetRepository();
78-
return repo.FullName == ActiveRepoName && SimpleApiClient.IsEnterprise();
79+
return (repo.FullName == ActiveRepoName || repo.Id == 0) && SimpleApiClient.IsEnterprise();
7980
}
80-
return true;
81+
return isdotcom;
8182
}
8283

8384
bool isEnabled;

src/GitHub.VisualStudio/GitHub.VisualStudio.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,9 @@
247247
<Compile Include="TeamExplorer\Home\IssuesNavigationItem.cs" />
248248
<Compile Include="TeamExplorer\Home\WikiNavigationItem.cs" />
249249
<Compile Include="TeamExplorer\Home\PulseNavigationItem.cs" />
250+
<Compile Include="TeamExplorer\Sync\EnsureLoggedInSectionSync.cs" />
250251
<Compile Include="TeamExplorer\Sync\GitHubPublishSection.cs" />
252+
<Compile Include="Base\EnsureLoggedInSection.cs" />
251253
<Compile Include="UI\DrawingExtensions.cs" />
252254
<Compile Include="UI\GitHubPane.cs" />
253255
<Compile Include="UI\Views\Controls\RepositoryCloneControl.xaml.cs">

src/GitHub.VisualStudio/Resources.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/GitHub.VisualStudio/Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,4 +276,7 @@
276276
<data name="WikiNavigationItemText" xml:space="preserve">
277277
<value>Wiki</value>
278278
</data>
279+
<data name="NotLoggedInMessage" xml:space="preserve">
280+
<value>You are not logged in to {0}, so certain git operations may fail. [Login now]({1})</value>
281+
</data>
279282
</root>

0 commit comments

Comments
 (0)