diff --git a/src/GitHub.App/Services/RepositoryCloneService.cs b/src/GitHub.App/Services/RepositoryCloneService.cs index e67a669146..a8bde09b5b 100644 --- a/src/GitHub.App/Services/RepositoryCloneService.cs +++ b/src/GitHub.App/Services/RepositoryCloneService.cs @@ -151,6 +151,7 @@ public async Task CloneOrOpenRepository( } } + // Give user a chance to choose a solution teamExplorerServices.ShowHomePage(); } diff --git a/src/GitHub.Exports/Services/VSServices.cs b/src/GitHub.Exports/Services/VSServices.cs index 01a811eb38..1bb1920cba 100644 --- a/src/GitHub.Exports/Services/VSServices.cs +++ b/src/GitHub.Exports/Services/VSServices.cs @@ -78,8 +78,9 @@ public bool TryOpenRepository(string repoPath) return false; } - var repoDir = os.Directory.GetDirectory(repoPath); - if (!repoDir.Exists) + var gitPath = Path.Combine(repoPath, ".git"); + var gitDir = os.Directory.GetDirectory(gitPath); + if (!gitDir.Exists) { return false; } diff --git a/src/GitHub.StartPage/StartPagePackage.cs b/src/GitHub.StartPage/StartPagePackage.cs index fc543b560a..245746f08a 100644 --- a/src/GitHub.StartPage/StartPagePackage.cs +++ b/src/GitHub.StartPage/StartPagePackage.cs @@ -1,5 +1,4 @@ using System; -using System.ComponentModel; using System.IO; using System.Runtime.InteropServices; using System.Threading; @@ -9,7 +8,6 @@ using GitHub.Primitives; using GitHub.Services; using GitHub.VisualStudio; -using Microsoft.TeamFoundation.Controls; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.CodeContainerManagement; using Microsoft.VisualStudio.Threading; @@ -59,7 +57,6 @@ async Task RunAcquisition(IProgress download try { var uiProvider = await Task.Run(() => Package.GetGlobalService(typeof(IGitHubServiceProvider)) as IGitHubServiceProvider); - await ShowTeamExplorerPage(uiProvider); request = await ShowCloneDialog(uiProvider, downloadProgress, repository); } catch (Exception e) @@ -84,35 +81,6 @@ async Task RunAcquisition(IProgress download lastAccessed: DateTimeOffset.UtcNow); } - async Task ShowTeamExplorerPage(IGitHubServiceProvider gitHubServiceProvider) - { - var te = gitHubServiceProvider?.GetService(typeof(ITeamExplorer)) as ITeamExplorer; - - if (te != null) - { - var page = te.NavigateToPage(new Guid(TeamExplorerPageIds.Connect), null); - - if (page == null) - { - var tcs = new TaskCompletionSource(); - PropertyChangedEventHandler handler = null; - - handler = new PropertyChangedEventHandler((s, e) => - { - if (e.PropertyName == "CurrentPage") - { - tcs.SetResult(te.CurrentPage); - te.PropertyChanged -= handler; - } - }); - - te.PropertyChanged += handler; - - page = await tcs.Task; - } - } - } - async Task ShowCloneDialog( IGitHubServiceProvider gitHubServiceProvider, IProgress progress, diff --git a/src/GitHub.TeamFoundation.14/Services/VSGitServices.cs b/src/GitHub.TeamFoundation.14/Services/VSGitServices.cs index cb1b9adfca..b51862deb1 100644 --- a/src/GitHub.TeamFoundation.14/Services/VSGitServices.cs +++ b/src/GitHub.TeamFoundation.14/Services/VSGitServices.cs @@ -5,10 +5,10 @@ #endif using System; +using System.Threading; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.ComponentModel.Composition; -using System.Globalization; using System.Linq; using System.Reactive.Linq; using System.Threading.Tasks; @@ -17,15 +17,12 @@ using GitHub.Models; using GitHub.TeamFoundation; using GitHub.VisualStudio; -#if TEAMEXPLORER14 +using Microsoft.TeamFoundation.Controls; using Microsoft.TeamFoundation.Git.Controls.Extensibility; -using ReactiveUI; -#else -using Microsoft.VisualStudio.Shell.Interop; -using System.Threading; -#endif using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility; +using ReactiveUI; using Serilog; +using Microsoft; namespace GitHub.Services { @@ -39,6 +36,8 @@ public class VSGitServices : IVSGitServices [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Used in VS2017")] readonly Lazy statusBar; + [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Used in VS2015")] + readonly Lazy vsServices; /// /// This MEF export requires specific versions of TeamFoundation. IGitExt is declared here so @@ -49,10 +48,13 @@ public class VSGitServices : IVSGitServices IGitExt gitExtService; [ImportingConstructor] - public VSGitServices(IGitHubServiceProvider serviceProvider, Lazy statusBar) + public VSGitServices(IGitHubServiceProvider serviceProvider, + Lazy statusBar, + Lazy vsServices) { this.serviceProvider = serviceProvider; this.statusBar = statusBar; + this.vsServices = vsServices; } // The Default Repository Path that VS uses is hidden in an internal @@ -81,25 +83,68 @@ public async Task Clone( bool recurseSubmodules, object progress = null) { -#if TEAMEXPLORER14 - var gitExt = serviceProvider.GetService(); - gitExt.Clone(cloneUrl, clonePath, recurseSubmodules ? CloneOptions.RecurseSubmodule : CloneOptions.None); + var teamExplorer = serviceProvider.TryGetService(); + Assumes.Present(teamExplorer); - // The operation will have completed when CanClone goes false and then true again. - await gitExt.WhenAnyValue(x => x.CanClone).Where(x => !x).Take(1); - await gitExt.WhenAnyValue(x => x.CanClone).Where(x => x).Take(1); +#if TEAMEXPLORER14 + await StartClonenOnConnectPageAsync(teamExplorer, cloneUrl, clonePath, recurseSubmodules); + NavigateToHomePage(teamExplorer); // Show progress on Team Explorer - Home + await WaitForCloneOnHomePageAsync(teamExplorer); + vsServices.Value.TryOpenRepository(clonePath); // Show the repository on Team Explorer - Home #else var gitExt = serviceProvider.GetService(); var typedProgress = ((Progress)progress) ?? new Progress(); + typedProgress.ProgressChanged += (s, e) => statusBar.Value.ShowMessage(e.ProgressText); + var cloneTask = gitExt.CloneAsync(cloneUrl, clonePath, recurseSubmodules, default(CancellationToken), typedProgress); - await Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.RunAsync(async () => - { - typedProgress.ProgressChanged += (s, e) => statusBar.Value.ShowMessage(e.ProgressText); - await gitExt.CloneAsync(cloneUrl, clonePath, recurseSubmodules, default(CancellationToken), typedProgress); - }); + NavigateToHomePage(teamExplorer); // Show progress on Team Explorer - Home + await cloneTask; #endif } + static async Task StartClonenOnConnectPageAsync( + ITeamExplorer teamExplorer, string cloneUrl, string clonePath, bool recurseSubmodules) + { + var connectPage = await NavigateToPageAsync(teamExplorer, new Guid(TeamExplorerPageIds.Connect)); + Assumes.Present(connectPage); + var gitExt = connectPage.GetService(); + Assumes.Present(gitExt); + + gitExt.Clone(cloneUrl, clonePath, recurseSubmodules ? CloneOptions.RecurseSubmodule : CloneOptions.None); + } + + static async Task WaitForCloneOnHomePageAsync(ITeamExplorer teamExplorer) + { + // The clone progress bar appears on the GettingStartedSection of the Home page, + // so we wait for this to be hidden before continuing. + var sectionId = new Guid("d0200918-c025-4cc3-9dee-4f5e89d0c918"); // GettingStartedSection + await teamExplorer + .WhenAnyValue(x => x.CurrentPage) + .Where(p => p.GetId() == new Guid(TeamExplorerPageIds.Home)) + .Select(p => p.GetSection(sectionId)) + .Where(s => s != null) + .Select(s => s.WhenAnyValue(x => x.IsVisible)) + .Switch() // Watch the topmost section + .StartWith(false) // If no events arrive default to invisible + .Throttle(TimeSpan.FromSeconds(1)) // Ignore glitch where section starts invisible + .Any(x => x == false); + } + + static void NavigateToHomePage(ITeamExplorer teamExplorer) + { + teamExplorer.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null); + } + + static async Task NavigateToPageAsync(ITeamExplorer teamExplorer, Guid pageId) + { + teamExplorer.NavigateToPage(pageId, null); + var page = await teamExplorer + .WhenAnyValue(x => x.CurrentPage) + .Where(x => x?.GetId() == pageId) + .Take(1); + return page; + } + IGitRepositoryInfo GetRepoFromVS() { gitExtService = serviceProvider.GetService(); diff --git a/test/GitHub.Exports.UnitTests/VSServicesTests.cs b/test/GitHub.Exports.UnitTests/VSServicesTests.cs index 9094551dad..1e7c7a010e 100644 --- a/test/GitHub.Exports.UnitTests/VSServicesTests.cs +++ b/test/GitHub.Exports.UnitTests/VSServicesTests.cs @@ -92,9 +92,10 @@ VSServices CreateVSServices(string repoDir, IOperatingSystem os = null, DTE dte if (repoDir != null) { + var gitDir = Path.Combine(repoDir, ".git"); var directoryInfo = Substitute.For(); directoryInfo.Exists.Returns(repoDirExists); - os.Directory.GetDirectory(repoDir).Returns(directoryInfo); + os.Directory.GetDirectory(gitDir).Returns(directoryInfo); } var provider = Substitute.For();