5
5
#endif
6
6
7
7
using System ;
8
+ using System . Threading ;
8
9
using System . Collections . Generic ;
9
10
using System . Diagnostics . CodeAnalysis ;
10
11
using System . ComponentModel . Composition ;
11
- using System . Globalization ;
12
12
using System . Linq ;
13
13
using System . Reactive . Linq ;
14
14
using System . Threading . Tasks ;
17
17
using GitHub . Models ;
18
18
using GitHub . TeamFoundation ;
19
19
using GitHub . VisualStudio ;
20
- #if TEAMEXPLORER14
20
+ using Microsoft . TeamFoundation . Controls ;
21
21
using Microsoft . TeamFoundation . Git . Controls . Extensibility ;
22
- using ReactiveUI ;
23
- #else
24
- using Microsoft . VisualStudio . Shell . Interop ;
25
- using System . Threading ;
26
- #endif
27
22
using Microsoft . VisualStudio . TeamFoundation . Git . Extensibility ;
23
+ using ReactiveUI ;
28
24
using Serilog ;
25
+ using Microsoft ;
29
26
30
27
namespace GitHub . Services
31
28
{
@@ -39,6 +36,8 @@ public class VSGitServices : IVSGitServices
39
36
40
37
[ SuppressMessage ( "Microsoft.Performance" , "CA1823:AvoidUnusedPrivateFields" , Justification = "Used in VS2017" ) ]
41
38
readonly Lazy < IStatusBarNotificationService > statusBar ;
39
+ [ SuppressMessage ( "Microsoft.Performance" , "CA1823:AvoidUnusedPrivateFields" , Justification = "Used in VS2015" ) ]
40
+ readonly Lazy < IVSServices > vsServices ;
42
41
43
42
/// <summary>
44
43
/// This MEF export requires specific versions of TeamFoundation. IGitExt is declared here so
@@ -49,10 +48,13 @@ public class VSGitServices : IVSGitServices
49
48
IGitExt gitExtService ;
50
49
51
50
[ ImportingConstructor ]
52
- public VSGitServices ( IGitHubServiceProvider serviceProvider , Lazy < IStatusBarNotificationService > statusBar )
51
+ public VSGitServices ( IGitHubServiceProvider serviceProvider ,
52
+ Lazy < IStatusBarNotificationService > statusBar ,
53
+ Lazy < IVSServices > vsServices )
53
54
{
54
55
this . serviceProvider = serviceProvider ;
55
56
this . statusBar = statusBar ;
57
+ this . vsServices = vsServices ;
56
58
}
57
59
58
60
// The Default Repository Path that VS uses is hidden in an internal
@@ -81,25 +83,68 @@ public async Task Clone(
81
83
bool recurseSubmodules ,
82
84
object progress = null )
83
85
{
84
- #if TEAMEXPLORER14
85
- var gitExt = serviceProvider . GetService < IGitRepositoriesExt > ( ) ;
86
- gitExt . Clone ( cloneUrl , clonePath , recurseSubmodules ? CloneOptions . RecurseSubmodule : CloneOptions . None ) ;
86
+ var teamExplorer = serviceProvider . TryGetService < ITeamExplorer > ( ) ;
87
+ Assumes . Present ( teamExplorer ) ;
87
88
88
- // The operation will have completed when CanClone goes false and then true again.
89
- await gitExt . WhenAnyValue ( x => x . CanClone ) . Where ( x => ! x ) . Take ( 1 ) ;
90
- await gitExt . WhenAnyValue ( x => x . CanClone ) . Where ( x => x ) . Take ( 1 ) ;
89
+ #if TEAMEXPLORER14
90
+ await StartClonenOnConnectPageAsync ( teamExplorer , cloneUrl , clonePath , recurseSubmodules ) ;
91
+ NavigateToHomePage ( teamExplorer ) ; // Show progress on Team Explorer - Home
92
+ await WaitForCloneOnHomePageAsync ( teamExplorer ) ;
93
+ vsServices . Value . TryOpenRepository ( clonePath ) ; // Show the repository on Team Explorer - Home
91
94
#else
92
95
var gitExt = serviceProvider . GetService < IGitActionsExt > ( ) ;
93
96
var typedProgress = ( ( Progress < ServiceProgressData > ) progress ) ?? new Progress < ServiceProgressData > ( ) ;
97
+ typedProgress . ProgressChanged += ( s , e ) => statusBar . Value . ShowMessage ( e . ProgressText ) ;
98
+ var cloneTask = gitExt . CloneAsync ( cloneUrl , clonePath , recurseSubmodules , default ( CancellationToken ) , typedProgress ) ;
94
99
95
- await Microsoft . VisualStudio . Shell . ThreadHelper . JoinableTaskFactory . RunAsync ( async ( ) =>
96
- {
97
- typedProgress . ProgressChanged += ( s , e ) => statusBar . Value . ShowMessage ( e . ProgressText ) ;
98
- await gitExt . CloneAsync ( cloneUrl , clonePath , recurseSubmodules , default ( CancellationToken ) , typedProgress ) ;
99
- } ) ;
100
+ NavigateToHomePage ( teamExplorer ) ; // Show progress on Team Explorer - Home
101
+ await cloneTask ;
100
102
#endif
101
103
}
102
104
105
+ static async Task StartClonenOnConnectPageAsync (
106
+ ITeamExplorer teamExplorer , string cloneUrl , string clonePath , bool recurseSubmodules )
107
+ {
108
+ var connectPage = await NavigateToPageAsync ( teamExplorer , new Guid ( TeamExplorerPageIds . Connect ) ) ;
109
+ Assumes . Present ( connectPage ) ;
110
+ var gitExt = connectPage . GetService < IGitRepositoriesExt > ( ) ;
111
+ Assumes . Present ( gitExt ) ;
112
+
113
+ gitExt . Clone ( cloneUrl , clonePath , recurseSubmodules ? CloneOptions . RecurseSubmodule : CloneOptions . None ) ;
114
+ }
115
+
116
+ static async Task WaitForCloneOnHomePageAsync ( ITeamExplorer teamExplorer )
117
+ {
118
+ // The clone progress bar appears on the GettingStartedSection of the Home page,
119
+ // so we wait for this to be hidden before continuing.
120
+ var sectionId = new Guid ( "d0200918-c025-4cc3-9dee-4f5e89d0c918" ) ; // GettingStartedSection
121
+ await teamExplorer
122
+ . WhenAnyValue ( x => x . CurrentPage )
123
+ . Where ( p => p . GetId ( ) == new Guid ( TeamExplorerPageIds . Home ) )
124
+ . Select ( p => p . GetSection ( sectionId ) )
125
+ . Where ( s => s != null )
126
+ . Select ( s => s . WhenAnyValue ( x => x . IsVisible ) )
127
+ . Switch ( ) // Watch the topmost section
128
+ . StartWith ( false ) // If no events arrive default to invisible
129
+ . Throttle ( TimeSpan . FromSeconds ( 1 ) ) // Ignore glitch where section starts invisible
130
+ . Any ( x => x == false ) ;
131
+ }
132
+
133
+ static void NavigateToHomePage ( ITeamExplorer teamExplorer )
134
+ {
135
+ teamExplorer . NavigateToPage ( new Guid ( TeamExplorerPageIds . Home ) , null ) ;
136
+ }
137
+
138
+ static async Task < ITeamExplorerPage > NavigateToPageAsync ( ITeamExplorer teamExplorer , Guid pageId )
139
+ {
140
+ teamExplorer . NavigateToPage ( pageId , null ) ;
141
+ var page = await teamExplorer
142
+ . WhenAnyValue ( x => x . CurrentPage )
143
+ . Where ( x => x ? . GetId ( ) == pageId )
144
+ . Take ( 1 ) ;
145
+ return page ;
146
+ }
147
+
103
148
IGitRepositoryInfo GetRepoFromVS ( )
104
149
{
105
150
gitExtService = serviceProvider . GetService < IGitExt > ( ) ;
0 commit comments