55#endif
66
77using System ;
8+ using System . Threading ;
89using System . Collections . Generic ;
910using System . Diagnostics . CodeAnalysis ;
1011using System . ComponentModel . Composition ;
11- using System . Globalization ;
1212using System . Linq ;
1313using System . Reactive . Linq ;
1414using System . Threading . Tasks ;
1717using GitHub . Models ;
1818using GitHub . TeamFoundation ;
1919using GitHub . VisualStudio ;
20- #if TEAMEXPLORER14
20+ using Microsoft . TeamFoundation . Controls ;
2121using Microsoft . TeamFoundation . Git . Controls . Extensibility ;
22- using ReactiveUI ;
23- #else
24- using Microsoft . VisualStudio . Shell . Interop ;
25- using System . Threading ;
26- #endif
2722using Microsoft . VisualStudio . TeamFoundation . Git . Extensibility ;
23+ using ReactiveUI ;
2824using Serilog ;
25+ using Microsoft ;
2926
3027namespace GitHub . Services
3128{
@@ -39,6 +36,8 @@ public class VSGitServices : IVSGitServices
3936
4037 [ SuppressMessage ( "Microsoft.Performance" , "CA1823:AvoidUnusedPrivateFields" , Justification = "Used in VS2017" ) ]
4138 readonly Lazy < IStatusBarNotificationService > statusBar ;
39+ [ SuppressMessage ( "Microsoft.Performance" , "CA1823:AvoidUnusedPrivateFields" , Justification = "Used in VS2015" ) ]
40+ readonly Lazy < IVSServices > vsServices ;
4241
4342 /// <summary>
4443 /// This MEF export requires specific versions of TeamFoundation. IGitExt is declared here so
@@ -49,10 +48,13 @@ public class VSGitServices : IVSGitServices
4948 IGitExt gitExtService ;
5049
5150 [ ImportingConstructor ]
52- public VSGitServices ( IGitHubServiceProvider serviceProvider , Lazy < IStatusBarNotificationService > statusBar )
51+ public VSGitServices ( IGitHubServiceProvider serviceProvider ,
52+ Lazy < IStatusBarNotificationService > statusBar ,
53+ Lazy < IVSServices > vsServices )
5354 {
5455 this . serviceProvider = serviceProvider ;
5556 this . statusBar = statusBar ;
57+ this . vsServices = vsServices ;
5658 }
5759
5860 // The Default Repository Path that VS uses is hidden in an internal
@@ -81,25 +83,68 @@ public async Task Clone(
8183 bool recurseSubmodules ,
8284 object progress = null )
8385 {
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 ) ;
8788
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
9194#else
9295 var gitExt = serviceProvider . GetService < IGitActionsExt > ( ) ;
9396 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 ) ;
9499
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 ;
100102#endif
101103 }
102104
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+
103148 IGitRepositoryInfo GetRepoFromVS ( )
104149 {
105150 gitExtService = serviceProvider . GetService < IGitExt > ( ) ;
0 commit comments