diff --git a/src/GitHub.App/Services/DialogService.cs b/src/GitHub.App/Services/DialogService.cs index ecce4a1cfa..e3f2c40f95 100644 --- a/src/GitHub.App/Services/DialogService.cs +++ b/src/GitHub.App/Services/DialogService.cs @@ -16,21 +16,31 @@ public class DialogService : IDialogService { readonly IViewViewModelFactory factory; readonly IShowDialogService showDialog; + readonly IGitHubContextService gitHubContextService; [ImportingConstructor] public DialogService( IViewViewModelFactory factory, - IShowDialogService showDialog) + IShowDialogService showDialog, + IGitHubContextService gitHubContextService) { Guard.ArgumentNotNull(factory, nameof(factory)); Guard.ArgumentNotNull(showDialog, nameof(showDialog)); + Guard.ArgumentNotNull(showDialog, nameof(gitHubContextService)); this.factory = factory; this.showDialog = showDialog; + this.gitHubContextService = gitHubContextService; } public async Task ShowCloneDialog(IConnection connection, string url = null) { + if (string.IsNullOrEmpty(url)) + { + var clipboardContext = gitHubContextService.FindContextFromClipboard(); + url = clipboardContext?.Url; + } + var viewModel = factory.CreateViewModel(); if (url != null) { diff --git a/src/GitHub.App/Services/GitHubContextService.cs b/src/GitHub.App/Services/GitHubContextService.cs index 640e85a659..8891995f31 100644 --- a/src/GitHub.App/Services/GitHubContextService.cs +++ b/src/GitHub.App/Services/GitHubContextService.cs @@ -3,6 +3,7 @@ using System.Text; using System.Linq; using System.Windows; +using System.Globalization; using System.Threading.Tasks; using System.Collections.Generic; using System.ComponentModel.Composition; @@ -25,6 +26,7 @@ public class GitHubContextService : IGitHubContextService { readonly IGitHubServiceProvider serviceProvider; readonly IGitService gitService; + readonly IVSServices vsServices; readonly Lazy textManager; // USERID_REGEX = /[a-z0-9][a-z0-9\-\_]*/i @@ -61,13 +63,38 @@ public class GitHubContextService : IGitHubContextService static readonly Regex tempFileObjectishRegex = new Regex(@"\\TFSTemp\\[^\\]*[.](?[a-z0-9]{8})[.][^.\\]*$", RegexOptions.Compiled); [ImportingConstructor] - public GitHubContextService(IGitHubServiceProvider serviceProvider, IGitService gitService) + public GitHubContextService(IGitHubServiceProvider serviceProvider, IGitService gitService, IVSServices vsServices) { this.serviceProvider = serviceProvider; this.gitService = gitService; + this.vsServices = vsServices; textManager = new Lazy(() => serviceProvider.GetService()); } + /// + public void TryNavigateToContext(string repositoryDir, GitHubContext context) + { + if (context?.LinkType == LinkType.Blob) + { + var (commitish, path, commitSha) = ResolveBlob(repositoryDir, context); + if (commitish == null && path == null) + { + var message = string.Format(CultureInfo.CurrentCulture, Resources.CouldntFindCorrespondingFile, context.Url); + vsServices.ShowMessageBoxInfo(message); + return; + } + + var hasChanges = HasChangesInWorkingDirectory(repositoryDir, commitish, path); + if (hasChanges) + { + var message = string.Format(CultureInfo.CurrentCulture, Resources.ChangesInWorkingDirectoryMessage, commitish); + vsServices.ShowMessageBoxInfo(message); + } + + TryOpenFile(repositoryDir, context); + } + } + /// public GitHubContext FindContextFromClipboard() { diff --git a/src/GitHub.App/Services/RepositoryCloneService.cs b/src/GitHub.App/Services/RepositoryCloneService.cs index a8bde09b5b..66febd6ba6 100644 --- a/src/GitHub.App/Services/RepositoryCloneService.cs +++ b/src/GitHub.App/Services/RepositoryCloneService.cs @@ -36,7 +36,9 @@ public class RepositoryCloneService : IRepositoryCloneService readonly IVSGitServices vsGitServices; readonly ITeamExplorerServices teamExplorerServices; readonly IGraphQLClientFactory graphqlFactory; + readonly IGitHubContextService gitHubContextService; readonly IUsageTracker usageTracker; + readonly Lazy dte; ICompiledQuery readViewerRepositories; [ImportingConstructor] @@ -45,13 +47,17 @@ public RepositoryCloneService( IVSGitServices vsGitServices, ITeamExplorerServices teamExplorerServices, IGraphQLClientFactory graphqlFactory, - IUsageTracker usageTracker) + IGitHubContextService gitHubContextService, + IUsageTracker usageTracker, + IGitHubServiceProvider sp) { this.operatingSystem = operatingSystem; this.vsGitServices = vsGitServices; this.teamExplorerServices = teamExplorerServices; this.graphqlFactory = graphqlFactory; + this.gitHubContextService = gitHubContextService; this.usageTracker = usageTracker; + dte = new Lazy(() => sp.GetService()); defaultClonePath = GetLocalClonePathFromGitProvider(operatingSystem.Environment.GetUserRepositoriesPath()); } @@ -125,7 +131,10 @@ public async Task CloneOrOpenRepository( var isDotCom = HostAddress.IsGitHubDotComUri(repositoryUrl); if (DestinationDirectoryExists(repositoryPath)) { - teamExplorerServices.OpenRepository(repositoryPath); + if (!IsSolutionInRepository(repositoryPath)) + { + teamExplorerServices.OpenRepository(repositoryPath); + } if (isDotCom) { @@ -153,6 +162,36 @@ public async Task CloneOrOpenRepository( // Give user a chance to choose a solution teamExplorerServices.ShowHomePage(); + + // Navigate to context for supported URL types (e.g. /blob/ URLs) + var context = gitHubContextService.FindContextFromUrl(url); + if (context != null) + { + gitHubContextService.TryNavigateToContext(repositoryPath, context); + } + } + + bool IsSolutionInRepository(string repositoryPath) + { + var solutionPath = dte.Value.Solution.FileName; + if (string.IsNullOrEmpty(solutionPath)) + { + return false; + } + + var isFolder = operatingSystem.Directory.DirectoryExists(solutionPath); + var solutionDir = isFolder ? solutionPath : Path.GetDirectoryName(solutionPath); + if (string.Equals(repositoryPath, solutionDir, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + if (solutionDir.StartsWith(repositoryPath + '\\', StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + return false; } /// diff --git a/src/GitHub.App/ViewModels/Dialog/Clone/RepositoryCloneViewModel.cs b/src/GitHub.App/ViewModels/Dialog/Clone/RepositoryCloneViewModel.cs index 12c51171e8..cc79920b9b 100644 --- a/src/GitHub.App/ViewModels/Dialog/Clone/RepositoryCloneViewModel.cs +++ b/src/GitHub.App/ViewModels/Dialog/Clone/RepositoryCloneViewModel.cs @@ -137,8 +137,8 @@ public async Task InitializeAsync(IConnection connection) this.WhenAnyValue(x => x.SelectedTabIndex).Subscribe(x => tabs[x].Activate().Forget()); - // Users in group A will see the URL tab by default - if (await IsGroupA().ConfigureAwait(false)) + // When a clipboard URL has been set or a user is in group A, show the URL tab by default + if (!string.IsNullOrEmpty(UrlTab.Url) || await IsGroupA().ConfigureAwait(false)) { SelectedTabIndex = 2; } diff --git a/src/GitHub.Exports/Services/IGitHubContextService.cs b/src/GitHub.Exports/Services/IGitHubContextService.cs index 8d8906233c..3f0536fe44 100644 --- a/src/GitHub.Exports/Services/IGitHubContextService.cs +++ b/src/GitHub.Exports/Services/IGitHubContextService.cs @@ -8,6 +8,13 @@ namespace GitHub.Services /// public interface IGitHubContextService { + /// + /// Attempt to navigate to the equivalent context inside Visual Studio. + /// + /// The target repository + /// The context to open. + void TryNavigateToContext(string repositoryDir, GitHubContext context); + /// /// Find the context from a URL in the clipboard if any. /// diff --git a/src/GitHub.Resources/Resources.Designer.cs b/src/GitHub.Resources/Resources.Designer.cs index 0f37fe583d..f67682e422 100644 --- a/src/GitHub.Resources/Resources.Designer.cs +++ b/src/GitHub.Resources/Resources.Designer.cs @@ -277,7 +277,7 @@ public static string ChangesCountFormat { } /// - /// Looks up a localized string similar to This file has changed since the permalink was created. + /// Looks up a localized string similar to The working file is different to the file at '{0}'. Please checkout the corresponding branch, pull request or commit.. /// public static string ChangesInWorkingDirectoryMessage { get { @@ -384,6 +384,15 @@ public static string couldNotConnectToTheServerText { } } + /// + /// Looks up a localized string similar to Couldn't find file corresponding to '{0}' in the repository. Please do a 'git fetch' or checkout the target pull request.. + /// + public static string CouldntFindCorrespondingFile { + get { + return ResourceManager.GetString("CouldntFindCorrespondingFile", resourceCulture); + } + } + /// /// Looks up a localized string similar to Couldn't find Git.exe on PATH. /// diff --git a/src/GitHub.Resources/Resources.resx b/src/GitHub.Resources/Resources.resx index 789c188593..6458eb80fb 100644 --- a/src/GitHub.Resources/Resources.resx +++ b/src/GitHub.Resources/Resources.resx @@ -810,7 +810,7 @@ https://git-scm.com/download/win There is no active repository to navigate - This file has changed since the permalink was created + The working file is different to the file at '{0}'. Please checkout the corresponding branch, pull request or commit. Please open the repository '{0}' and try again @@ -845,4 +845,7 @@ https://git-scm.com/download/win Please rename one of your existing remotes to 'origin' or add a new remote named 'origin' and fetch. This can be done from the command line or by clicking the button below. + + Couldn't find file corresponding to '{0}' in the repository. Please do a 'git fetch' or checkout the target pull request. + \ No newline at end of file diff --git a/src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs b/src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs index f0bb5358ff..17a12f0652 100644 --- a/src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs +++ b/src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs @@ -12,8 +12,6 @@ namespace GitHub.VisualStudio.Commands [Export(typeof(IOpenFromClipboardCommand))] public class OpenFromClipboardCommand : VsCommand, IOpenFromClipboardCommand { - - readonly Lazy gitHubContextService; readonly Lazy teamExplorerContext; readonly Lazy vsServices; diff --git a/src/GitHub.VisualStudio/Commands/OpenFromUrlCommand.cs b/src/GitHub.VisualStudio/Commands/OpenFromUrlCommand.cs index 00756a5c09..2a330dd76f 100644 --- a/src/GitHub.VisualStudio/Commands/OpenFromUrlCommand.cs +++ b/src/GitHub.VisualStudio/Commands/OpenFromUrlCommand.cs @@ -11,7 +11,6 @@ namespace GitHub.VisualStudio.Commands public class OpenFromUrlCommand : VsCommand, IOpenFromUrlCommand { readonly Lazy dialogService; - readonly Lazy gitHubContextService; readonly Lazy repositoryCloneService; /// @@ -27,12 +26,10 @@ public class OpenFromUrlCommand : VsCommand, IOpenFromUrlCommand [ImportingConstructor] public OpenFromUrlCommand( Lazy dialogService, - Lazy gitHubContextService, Lazy repositoryCloneService) : base(CommandSet, CommandId) { this.dialogService = dialogService; - this.gitHubContextService = gitHubContextService; this.repositoryCloneService = repositoryCloneService; // See https://code.msdn.microsoft.com/windowsdesktop/AllowParams-2005-9442298f @@ -41,12 +38,6 @@ public OpenFromUrlCommand( public override async Task Execute(string url) { - if (string.IsNullOrEmpty(url)) - { - var clipboardContext = gitHubContextService.Value.FindContextFromClipboard(); - url = clipboardContext?.Url; - } - var cloneDialogResult = await dialogService.Value.ShowCloneDialog(null, url); if (cloneDialogResult != null) { diff --git a/test/GitHub.App.UnitTests/Services/GitHubContextServiceTests.cs b/test/GitHub.App.UnitTests/Services/GitHubContextServiceTests.cs index 01fc6ba496..5ebf5458ed 100644 --- a/test/GitHub.App.UnitTests/Services/GitHubContextServiceTests.cs +++ b/test/GitHub.App.UnitTests/Services/GitHubContextServiceTests.cs @@ -498,8 +498,9 @@ static GitHubContextService CreateGitHubContextService(string repositoryDir = nu { var sp = Substitute.For(); var gitService = Substitute.For(); + var vsServices = Substitute.For(); gitService.GetRepository(repositoryDir).Returns(repository); - return new GitHubContextService(sp, gitService); + return new GitHubContextService(sp, gitService, vsServices); } } diff --git a/test/GitHub.App.UnitTests/Services/RepositoryCloneServiceTests.cs b/test/GitHub.App.UnitTests/Services/RepositoryCloneServiceTests.cs index a68eb76e8f..d3941f8798 100644 --- a/test/GitHub.App.UnitTests/Services/RepositoryCloneServiceTests.cs +++ b/test/GitHub.App.UnitTests/Services/RepositoryCloneServiceTests.cs @@ -7,7 +7,6 @@ using System.Linq.Expressions; using System; using GitHub.Models; -using GitHub.Api; public class RepositoryCloneServiceTests { @@ -16,10 +15,10 @@ public class TheCloneRepositoryMethod : TestBaseClass [Test] public async Task ClonesToRepositoryPathAsync() { - var serviceProvider = Substitutes.ServiceProvider; + var serviceProvider = Substitutes.GetServiceProvider(); var operatingSystem = serviceProvider.GetOperatingSystem(); var vsGitServices = serviceProvider.GetVSGitServices(); - var cloneService = serviceProvider.GetRepositoryCloneService(); + var cloneService = CreateRepositoryCloneService(serviceProvider); await cloneService.CloneRepository("https://github.com/foo/bar", @"c:\dev\bar"); @@ -35,13 +34,9 @@ public async Task ClonesToRepositoryPathAsync() [TestCase("https://enterprise.com/foo/bar", 0, nameof(UsageModel.MeasuresModel.NumberOfGitHubClones))] public async Task UpdatesMetricsWhenRepositoryClonedAsync(string cloneUrl, int numberOfCalls, string counterName) { - var serviceProvider = Substitutes.ServiceProvider; - var operatingSystem = serviceProvider.GetOperatingSystem(); - var vsGitServices = serviceProvider.GetVSGitServices(); - var teamExplorerServices = Substitute.For(); - var graphqlFactory = Substitute.For(); - var usageTracker = Substitute.For(); - var cloneService = new RepositoryCloneService(operatingSystem, vsGitServices, teamExplorerServices, graphqlFactory, usageTracker); + var serviceProvider = Substitutes.GetServiceProvider(); + var usageTracker = serviceProvider.GetUsageTracker(); + var cloneService = CreateRepositoryCloneService(serviceProvider); await cloneService.CloneRepository(cloneUrl, @"c:\dev\bar"); var model = UsageModel.Create(Guid.NewGuid()); @@ -51,6 +46,36 @@ await usageTracker.Received(numberOfCalls).IncrementCounter( ((MemberExpression)x.Body).Member.Name == counterName)); } + [TestCase(@"c:\repository", "", true, 1)] + [TestCase(@"c:\repository", @"c:\solution", true, 1)] + [TestCase(@"c:\already\open", @"c:\already\open", true, 0)] + [TestCase(@"c:\already\open", @"c:\already\open\nested", true, 0, Description = "Solution folder in repository")] + [TestCase(@"c:\already\open", @"c:\already\open\my.sln", false, 0)] + [TestCase(@"c:\already\open", @"c:\already\open\nested\my.sln", false, 0)] + [TestCase(@"c:\already\open\nested", @"c:\already\open", true, 1, Description = "Repository in solution folder")] + public async Task Skip_OpenRepository_When_Already_Open(string repositoryPath, string solutionPath, + bool isFolder, int openRepository) + { + var repositoryUrl = "https://github.com/owner/repo"; + var cloneDialogResult = new CloneDialogResult(repositoryPath, repositoryUrl); + var serviceProvider = Substitutes.GetServiceProvider(); + var operatingSystem = serviceProvider.GetOperatingSystem(); + operatingSystem.Directory.DirectoryExists(repositoryPath).Returns(true); + var dte = Substitute.For(); + serviceProvider.GetService().Returns(dte); + dte.Solution.FileName.Returns(solutionPath); + if (isFolder) + { + operatingSystem.Directory.DirectoryExists(solutionPath).Returns(true); + } + var cloneService = CreateRepositoryCloneService(serviceProvider); + + await cloneService.CloneOrOpenRepository(cloneDialogResult); + + var teamExplorerServices = serviceProvider.GetTeamExplorerServices(); + teamExplorerServices.Received(openRepository).OpenRepository(repositoryPath); + } + [TestCase("https://github.com/foo/bar", false, 1, nameof(UsageModel.MeasuresModel.NumberOfClones))] [TestCase("https://github.com/foo/bar", false, 1, nameof(UsageModel.MeasuresModel.NumberOfGitHubClones))] [TestCase("https://github.com/foo/bar", false, 0, nameof(UsageModel.MeasuresModel.NumberOfEnterpriseClones))] @@ -66,15 +91,11 @@ public async Task UpdatesMetricsWhenCloneOrOpenRepositoryAsync(string cloneUrl, { var repositoryPath = @"c:\dev\bar"; var cloneDialogResult = new CloneDialogResult(repositoryPath, cloneUrl); - var serviceProvider = Substitutes.ServiceProvider; + var serviceProvider = Substitutes.GetServiceProvider(); var operatingSystem = serviceProvider.GetOperatingSystem(); operatingSystem.Directory.DirectoryExists(repositoryPath).Returns(dirExists); - var vsGitServices = serviceProvider.GetVSGitServices(); - var teamExplorerServices = Substitute.For(); - var graphqlFactory = Substitute.For(); - var usageTracker = Substitute.For(); - var cloneService = new RepositoryCloneService(operatingSystem, vsGitServices, teamExplorerServices, - graphqlFactory, usageTracker); + var usageTracker = serviceProvider.GetUsageTracker(); + var cloneService = CreateRepositoryCloneService(serviceProvider); await cloneService.CloneOrOpenRepository(cloneDialogResult); @@ -87,15 +108,11 @@ await usageTracker.Received(numberOfCalls).IncrementCounter( [TestCase(@"c:\not_default\repo", @"c:\default", 0, nameof(UsageModel.MeasuresModel.NumberOfClonesToDefaultClonePath))] public async Task UpdatesMetricsWhenDefaultClonePath(string targetPath, string defaultPath, int numberOfCalls, string counterName) { - var serviceProvider = Substitutes.ServiceProvider; - var operatingSystem = serviceProvider.GetOperatingSystem(); + var serviceProvider = Substitutes.GetServiceProvider(); var vsGitServices = serviceProvider.GetVSGitServices(); - var teamExplorerServices = Substitute.For(); vsGitServices.GetLocalClonePathFromGitProvider().Returns(defaultPath); - var graphqlFactory = Substitute.For(); - var usageTracker = Substitute.For(); - var cloneService = new RepositoryCloneService(operatingSystem, vsGitServices, teamExplorerServices, - graphqlFactory, usageTracker); + var usageTracker = serviceProvider.GetUsageTracker(); + var cloneService = CreateRepositoryCloneService(serviceProvider); await cloneService.CloneRepository("https://github.com/foo/bar", targetPath); var model = UsageModel.Create(Guid.NewGuid()); @@ -104,5 +121,11 @@ await usageTracker.Received(numberOfCalls).IncrementCounter( Arg.Is>>(x => ((MemberExpression)x.Body).Member.Name == counterName)); } + + static RepositoryCloneService CreateRepositoryCloneService(IGitHubServiceProvider sp) + { + return new RepositoryCloneService(sp.GetOperatingSystem(), sp.GetVSGitServices(), sp.GetTeamExplorerServices(), + sp.GetGraphQLClientFactory(), sp.GetGitHubContextService(), sp.GetUsageTracker(), sp); + } } } diff --git a/test/GitHub.App.UnitTests/Substitutes.cs b/test/GitHub.App.UnitTests/Substitutes.cs index a0e9fa5628..ac707407f8 100644 --- a/test/GitHub.App.UnitTests/Substitutes.cs +++ b/test/GitHub.App.UnitTests/Substitutes.cs @@ -112,12 +112,17 @@ public static IGitHubServiceProvider GetServiceProvider( var os = OperatingSystem; var vsgit = IVSGitServices; var clone = cloneService ?? new RepositoryCloneService(os, vsgit, Substitute.For(), - Substitute.For(), Substitute.For()); + Substitute.For(), Substitute.For(), + Substitute.For(), ret); var create = creationService ?? new RepositoryCreationService(clone); avatarProvider = avatarProvider ?? Substitute.For(); - //ret.GetService(typeof(IGitRepositoriesExt)).Returns(IGitRepositoriesExt); ret.GetService(typeof(IGitService)).Returns(gitservice); ret.GetService(typeof(IVSServices)).Returns(Substitute.For()); + ret.GetService(typeof(ITeamExplorerServices)).Returns(Substitute.For()); + ret.GetService(typeof(IGraphQLClientFactory)).Returns(Substitute.For()); + ret.GetService(typeof(IGitHubContextService)).Returns(Substitute.For()); + ret.GetService(typeof(IVSGitExt)).Returns(Substitute.For()); + ret.GetService(typeof(IUsageTracker)).Returns(Substitute.For()); ret.GetService(typeof(IVSGitServices)).Returns(vsgit); ret.GetService(typeof(IOperatingSystem)).Returns(os); ret.GetService(typeof(IRepositoryCloneService)).Returns(clone); @@ -132,16 +137,36 @@ public static IGitHubServiceProvider GetServiceProvider( return ret; } - //public static IGitRepositoriesExt GetGitExt(this IServiceProvider provider) - //{ - // return provider.GetService(typeof(IGitRepositoriesExt)) as IGitRepositoriesExt; - //} - public static IVSServices GetVSServices(this IServiceProvider provider) { return provider.GetService(typeof(IVSServices)) as IVSServices; } + public static ITeamExplorerServices GetTeamExplorerServices(this IServiceProvider provider) + { + return provider.GetService(typeof(ITeamExplorerServices)) as ITeamExplorerServices; + } + + public static IGraphQLClientFactory GetGraphQLClientFactory(this IServiceProvider provider) + { + return provider.GetService(typeof(IGraphQLClientFactory)) as IGraphQLClientFactory; + } + + public static IGitHubContextService GetGitHubContextService(this IServiceProvider provider) + { + return provider.GetService(typeof(IGitHubContextService)) as IGitHubContextService; + } + + public static IVSGitExt GetVSGitExt(this IServiceProvider provider) + { + return provider.GetService(typeof(IVSGitExt)) as IVSGitExt; + } + + public static IUsageTracker GetUsageTracker(this IServiceProvider provider) + { + return provider.GetService(typeof(IUsageTracker)) as IUsageTracker; + } + public static IVSGitServices GetVSGitServices(this IServiceProvider provider) { return provider.GetService(typeof(IVSGitServices)) as IVSGitServices; diff --git a/test/GitHub.App.UnitTests/ViewModels/Dialog/Clone/RepositoryCloneViewModelTests.cs b/test/GitHub.App.UnitTests/ViewModels/Dialog/Clone/RepositoryCloneViewModelTests.cs index a4a51b702b..b310a69122 100644 --- a/test/GitHub.App.UnitTests/ViewModels/Dialog/Clone/RepositoryCloneViewModelTests.cs +++ b/test/GitHub.App.UnitTests/ViewModels/Dialog/Clone/RepositoryCloneViewModelTests.cs @@ -35,16 +35,19 @@ public async Task GitHubPage_Is_Initialized() target.EnterpriseTab.DidNotReceiveWithAnyArgs().Initialize(null); } - [TestCase("https://github.com", false, 0)] - [TestCase("https://enterprise.com", false, 1)] - [TestCase("https://github.com", true, 2, Description = "Show URL tab for GitHub connections")] - [TestCase("https://enterprise.com", true, 2, Description = "Show URL tab for Enterprise connections")] - public async Task Default_SelectedTabIndex_For_Group(string address, bool isGroupA, int expectTabIndex) + [TestCase("https://github.com", null, false, 0)] + [TestCase("https://enterprise.com", null, false, 1)] + [TestCase("https://github.com", null, true, 2, Description = "Show URL tab for GitHub connections")] + [TestCase("https://enterprise.com", null, true, 2, Description = "Show URL tab for Enterprise connections")] + [TestCase("https://github.com", "https://github.com/github/visualstudio", false, 2)] + [TestCase("https://enterprise.com", "https://enterprise.com/owner/repo", false, 2)] + public async Task Default_SelectedTabIndex_For_Group(string address, string clipboardUrl, bool isGroupA, int expectTabIndex) { var cm = CreateConnectionManager(address); var connection = cm.Connections[0]; var usageService = CreateUsageService(isGroupA); var target = CreateTarget(connectionManager: cm, usageService: usageService); + target.UrlTab.Url = clipboardUrl; await target.InitializeAsync(connection); diff --git a/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs b/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs index a29b9a8afe..0548fef04f 100644 --- a/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs +++ b/test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs @@ -169,7 +169,7 @@ static GitHubContext CreateGitHubContext(UriString uri = null, string owner = "g { uri = uri ?? new UriString($"https://github.com/{owner}/{repositoryName}/blob/{branch}/README.md"); - return new GitHubContextService(null, null).FindContextFromUrl(uri); + return new GitHubContextService(null, null, null).FindContextFromUrl(uri); } static OpenFromClipboardCommand CreateOpenFromClipboardCommand( diff --git a/test/GitHub.VisualStudio.UnitTests/Substitutes.cs b/test/GitHub.VisualStudio.UnitTests/Substitutes.cs index a0e9fa5628..7a22304bae 100644 --- a/test/GitHub.VisualStudio.UnitTests/Substitutes.cs +++ b/test/GitHub.VisualStudio.UnitTests/Substitutes.cs @@ -112,10 +112,10 @@ public static IGitHubServiceProvider GetServiceProvider( var os = OperatingSystem; var vsgit = IVSGitServices; var clone = cloneService ?? new RepositoryCloneService(os, vsgit, Substitute.For(), - Substitute.For(), Substitute.For()); + Substitute.For(), Substitute.For(), + Substitute.For(), ret); var create = creationService ?? new RepositoryCreationService(clone); avatarProvider = avatarProvider ?? Substitute.For(); - //ret.GetService(typeof(IGitRepositoriesExt)).Returns(IGitRepositoriesExt); ret.GetService(typeof(IGitService)).Returns(gitservice); ret.GetService(typeof(IVSServices)).Returns(Substitute.For()); ret.GetService(typeof(IVSGitServices)).Returns(vsgit); @@ -132,11 +132,6 @@ public static IGitHubServiceProvider GetServiceProvider( return ret; } - //public static IGitRepositoriesExt GetGitExt(this IServiceProvider provider) - //{ - // return provider.GetService(typeof(IGitRepositoriesExt)) as IGitRepositoriesExt; - //} - public static IVSServices GetVSServices(this IServiceProvider provider) { return provider.GetService(typeof(IVSServices)) as IVSServices;