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

Commit 2c61005

Browse files
committed
Merge master into feature/link-to-vs
2 parents 172aba3 + 2a676a1 commit 2c61005

File tree

52 files changed

+605
-259
lines changed

Some content is hidden

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

52 files changed

+605
-259
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ Official builds of this extension are available at [the official website](https:
77

88
[![Join the chat at https://gitter.im/github/VisualStudio](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/github/VisualStudio?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
99

10+
## Installing beta versions
11+
12+
Older and pre-release/beta/untested versions are available at [the releases page](https://github.com/github/VisualStudio/releases), and also via a custom gallery feed for Visual Studio.
13+
14+
You can configure the gallery by going to `Tools / Options / Extensions and Updates` and adding a new gallery with the url https://visualstudio.github.com/releases/feed.rss. The gallery will now be available from `Tools / Extensions and Updates`.
15+
16+
Beta releases will have `(beta)` in their title in the gallery, following the version number. You can view the release notes in the gallery by hovering over the description, or by clicking the `Release Notes` link on the right side.
17+
1018
## Build requirements
1119

1220
* Visual Studio 2015

deploy-local.cmd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
powershell.exe .\script\deploy.ps1 production None -Force -NoChat -NoPush -NoUpload

documentation/manifest.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,6 @@
110110
- [ ] Login button is disabled
111111
- [ ] **Login to an enterprise instance**
112112
- [ ] Team Explorer Connect page shows two github connections - one titled GitHub, another with the enterprise url
113+
- [ ] **Login with 2FA on**
114+
- [ ] Login GitHub with 2FA turned on
115+
- [ ] Resend works

script

src/CredentialManagement/Credential.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public Credential(
5656
Password = password;
5757
Target = target;
5858
Type = CredentialType.Generic;
59-
PersistenceType = PersistenceType.Session;
59+
PersistenceType = PersistenceType.LocalComputer;
6060
_lastWriteTime = DateTime.MinValue;
6161
}
6262

src/GitHub.App/Controllers/UIController.cs

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using ReactiveUI;
1919
using Stateless;
2020
using System.Collections.Specialized;
21+
using System.Linq;
2122

2223
namespace GitHub.Controllers
2324
{
@@ -121,6 +122,7 @@ public UIController(IUIProvider uiProvider, IRepositoryHosts hosts, IExportFacto
121122
machine.Configure(UIViewType.End)
122123
.OnEntryFrom(Trigger.Cancel, () => End(false))
123124
.OnEntryFrom(Trigger.Next, () => End(true))
125+
.OnEntryFrom(Trigger.Finish, () => End(true))
124126
.Permit(Trigger.Next, UIViewType.Finished);
125127

126128
machine.Configure(UIViewType.Finished);
@@ -151,10 +153,9 @@ public IObservable<bool> ListenToCompletionState()
151153
void End(bool success)
152154
{
153155
uiProvider.RemoveService(typeof(IConnection));
154-
transition.OnCompleted();
155156
completion?.OnNext(success);
156157
completion?.OnCompleted();
157-
completion = null;
158+
transition.OnCompleted();
158159
}
159160

160161
void RunView(UIViewType viewType)
@@ -226,7 +227,11 @@ public void Start([AllowNull] IConnection connection)
226227
{
227228
if (connection != null)
228229
{
229-
uiProvider.AddService(typeof(IConnection), connection);
230+
if (currentFlow != UIControllerFlow.Authentication)
231+
uiProvider.AddService(connection);
232+
else // sanity check: it makes zero sense to pass a connection in when calling the auth flow
233+
Debug.Assert(false, "Calling the auth flow with a connection makes no sense!");
234+
230235
connection.Login()
231236
.Select(c => hosts.LookupHost(connection.HostAddress))
232237
.Do(host =>
@@ -250,16 +255,26 @@ public void Start([AllowNull] IConnection connection)
250255
else
251256
{
252257
connectionManager
253-
.IsLoggedIn(hosts)
254-
.Do(loggedin =>
258+
.GetLoggedInConnections(hosts)
259+
.FirstOrDefaultAsync()
260+
.Select(c =>
255261
{
256-
if (!loggedin && currentFlow != UIControllerFlow.Authentication)
262+
bool loggedin = c != null;
263+
if (currentFlow != UIControllerFlow.Authentication)
257264
{
258-
connectionAdded = (s, e) => {
259-
if (e.Action == NotifyCollectionChangedAction.Add)
260-
uiProvider.AddService(typeof(IConnection), e.NewItems[0]);
261-
};
262-
connectionManager.Connections.CollectionChanged += connectionAdded;
265+
if (loggedin) // register the first available connection so the viewmodel can use it
266+
uiProvider.AddService(c);
267+
else
268+
{
269+
// a connection will be added to the list when auth is done, register it so the next
270+
// viewmodel can use it
271+
connectionAdded = (s, e) =>
272+
{
273+
if (e.Action == NotifyCollectionChangedAction.Add)
274+
uiProvider.AddService(typeof(IConnection), e.NewItems[0]);
275+
};
276+
connectionManager.Connections.CollectionChanged += connectionAdded;
277+
}
263278
}
264279

265280
machine.Configure(UIViewType.None)
@@ -270,6 +285,8 @@ public void Start([AllowNull] IConnection connection)
270285
.PermitIf(Trigger.Clone, UIViewType.Login, () => !loggedin)
271286
.PermitIf(Trigger.Publish, UIViewType.Publish, () => loggedin)
272287
.PermitIf(Trigger.Publish, UIViewType.Login, () => !loggedin);
288+
289+
return loggedin;
273290
})
274291
.ObserveOn(RxApp.MainThreadScheduler)
275292
.Subscribe(_ => { }, () =>
@@ -292,15 +309,19 @@ protected virtual void Dispose(bool disposing)
292309
if (disposing)
293310
{
294311
if (disposed) return;
312+
disposed = true;
295313

296-
Debug.WriteLine("Disposing ({0})", GetHashCode());
297-
disposables.Dispose();
298-
transition?.Dispose();
299-
completion?.Dispose();
300314
if (connectionAdded != null)
301315
connectionManager.Connections.CollectionChanged -= connectionAdded;
302316
connectionAdded = null;
303-
disposed = true;
317+
318+
var tr = transition;
319+
var cmp = completion;
320+
transition = null;
321+
completion = null;
322+
disposables.Dispose();
323+
tr?.Dispose();
324+
cmp?.Dispose();
304325
}
305326
}
306327

src/GitHub.App/Models/ConnectionRepositoryHostMap.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public class ConnectionRepositoryHostMap : IConnectionRepositoryHostMap
1010
{
1111
[ImportingConstructor]
1212
public ConnectionRepositoryHostMap(IUIProvider provider, IRepositoryHosts hosts)
13-
: this(provider.GetService<IConnection>(), hosts)
13+
: this(provider.TryGetService<IConnection>(), hosts)
1414
{
1515
}
1616

src/GitHub.App/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.App/Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@
153153
<data name="PublishToTitle" xml:space="preserve">
154154
<value>Publish repository to {0}</value>
155155
</data>
156+
<data name="RepositoryCloneFailedNoSelectedRepo" xml:space="preserve">
157+
<value>No selected repository.</value>
158+
</data>
156159
<data name="RepositoryCreationFailedAlreadyExists" xml:space="preserve">
157160
<value>Repository '{0}/{1}' already exists.</value>
158161
</data>

src/GitHub.App/ViewModels/RepositoryCloneViewModel.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class RepositoryCloneViewModel : BaseViewModel, IRepositoryCloneViewModel
2727
readonly IRepositoryHost repositoryHost;
2828
readonly IRepositoryCloneService cloneService;
2929
readonly IOperatingSystem operatingSystem;
30-
readonly IVSServices vsServices;
30+
readonly INotificationService notificationService;
3131
readonly IReactiveCommand<IReadOnlyList<IRepositoryModel>> loadRepositoriesCommand;
3232
readonly ReactiveCommand<object> browseForDirectoryCommand = ReactiveCommand.Create();
3333
readonly ObservableAsPropertyHelper<bool> isLoading;
@@ -41,20 +41,20 @@ public class RepositoryCloneViewModel : BaseViewModel, IRepositoryCloneViewModel
4141
IConnectionRepositoryHostMap connectionRepositoryHostMap,
4242
IRepositoryCloneService repositoryCloneService,
4343
IOperatingSystem operatingSystem,
44-
IVSServices vsServices)
45-
: this(connectionRepositoryHostMap.CurrentRepositoryHost, repositoryCloneService, operatingSystem, vsServices)
44+
INotificationService notificationService)
45+
: this(connectionRepositoryHostMap.CurrentRepositoryHost, repositoryCloneService, operatingSystem, notificationService)
4646
{ }
4747

4848
public RepositoryCloneViewModel(
4949
IRepositoryHost repositoryHost,
5050
IRepositoryCloneService cloneService,
5151
IOperatingSystem operatingSystem,
52-
IVSServices vsServices)
52+
INotificationService notificationService)
5353
{
5454
this.repositoryHost = repositoryHost;
5555
this.cloneService = cloneService;
5656
this.operatingSystem = operatingSystem;
57-
this.vsServices = vsServices;
57+
this.notificationService = notificationService;
5858

5959
Title = string.Format(CultureInfo.CurrentCulture, Resources.CloneTitle, repositoryHost.Title);
6060
Repositories = new ReactiveList<IRepositoryModel>();
@@ -120,6 +120,11 @@ IObservable<Unit> OnCloneRepository(object state)
120120
{
121121
var repository = SelectedRepository;
122122
Debug.Assert(repository != null, "Should not be able to attempt to clone a repo when it's null");
123+
if (repository == null)
124+
{
125+
notificationService.ShowError(Resources.RepositoryCloneFailedNoSelectedRepo);
126+
return Observable.Return(Unit.Default);
127+
}
123128
// The following is a noop if the directory already exists.
124129
operatingSystem.Directory.CreateDirectory(BaseRepositoryPath);
125130
return cloneService.CloneRepository(repository.CloneUrl, repository.Name, BaseRepositoryPath);
@@ -129,7 +134,7 @@ IObservable<Unit> OnCloneRepository(object state)
129134
{
130135
var repository = SelectedRepository;
131136
Debug.Assert(repository != null, "Should not be able to attempt to clone a repo when it's null");
132-
vsServices.ShowError(e.GetUserFriendlyErrorMessage(ErrorType.ClonedFailed, repository.Name));
137+
notificationService.ShowError(e.GetUserFriendlyErrorMessage(ErrorType.ClonedFailed, repository.Name));
133138
return Observable.Return(Unit.Default);
134139
});
135140
}

0 commit comments

Comments
 (0)