Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/GitHub.App/Services/DialogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<CloneDialogResult> ShowCloneDialog(IConnection connection, string url = null)
{
if (string.IsNullOrEmpty(url))
{
var clipboardContext = gitHubContextService.FindContextFromClipboard();
url = clipboardContext?.Url;
}

var viewModel = factory.CreateViewModel<IRepositoryCloneViewModel>();
if (url != null)
{
Expand Down
29 changes: 28 additions & 1 deletion src/GitHub.App/Services/GitHubContextService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,6 +26,7 @@ public class GitHubContextService : IGitHubContextService
{
readonly IGitHubServiceProvider serviceProvider;
readonly IGitService gitService;
readonly IVSServices vsServices;
readonly Lazy<IVsTextManager2> textManager;

// USERID_REGEX = /[a-z0-9][a-z0-9\-\_]*/i
Expand Down Expand Up @@ -61,13 +63,38 @@ public class GitHubContextService : IGitHubContextService
static readonly Regex tempFileObjectishRegex = new Regex(@"\\TFSTemp\\[^\\]*[.](?<objectish>[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<IVsTextManager2>(() => serviceProvider.GetService<SVsTextManager, IVsTextManager2>());
}

/// <inheritdoc/>
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);
}
}

/// <inheritdoc/>
public GitHubContext FindContextFromClipboard()
{
Expand Down
43 changes: 41 additions & 2 deletions src/GitHub.App/Services/RepositoryCloneService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<EnvDTE.DTE> dte;
ICompiledQuery<ViewerRepositoriesModel> readViewerRepositories;

[ImportingConstructor]
Expand All @@ -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<EnvDTE.DTE>(() => sp.GetService<EnvDTE.DTE>());

defaultClonePath = GetLocalClonePathFromGitProvider(operatingSystem.Environment.GetUserRepositoriesPath());
}
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
7 changes: 7 additions & 0 deletions src/GitHub.Exports/Services/IGitHubContextService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ namespace GitHub.Services
/// </summary>
public interface IGitHubContextService
{
/// <summary>
/// Attempt to navigate to the equivalent context inside Visual Studio.
/// </summary>
/// <param name="repositoryDir">The target repository</param>
/// <param name="context">The context to open.</param>
void TryNavigateToContext(string repositoryDir, GitHubContext context);

/// <summary>
/// Find the context from a URL in the clipboard if any.
/// </summary>
Expand Down
11 changes: 10 additions & 1 deletion src/GitHub.Resources/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion src/GitHub.Resources/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ https://git-scm.com/download/win</value>
<value>There is no active repository to navigate</value>
</data>
<data name="ChangesInWorkingDirectoryMessage" xml:space="preserve">
<value>This file has changed since the permalink was created</value>
<value>The working file is different to the file at '{0}'. Please checkout the corresponding branch, pull request or commit.</value>
</data>
<data name="DifferentRepositoryMessage" xml:space="preserve">
<value>Please open the repository '{0}' and try again</value>
Expand Down Expand Up @@ -845,4 +845,7 @@ https://git-scm.com/download/win</value>
<data name="RepositoriesMustHaveRemoteOriginHowToFix" xml:space="preserve">
<value>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.</value>
</data>
<data name="CouldntFindCorrespondingFile" xml:space="preserve">
<value>Couldn't find file corresponding to '{0}' in the repository. Please do a 'git fetch' or checkout the target pull request.</value>
</data>
</root>
2 changes: 0 additions & 2 deletions src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ namespace GitHub.VisualStudio.Commands
[Export(typeof(IOpenFromClipboardCommand))]
public class OpenFromClipboardCommand : VsCommand<string>, IOpenFromClipboardCommand
{


readonly Lazy<IGitHubContextService> gitHubContextService;
readonly Lazy<ITeamExplorerContext> teamExplorerContext;
readonly Lazy<IVSServices> vsServices;
Expand Down
9 changes: 0 additions & 9 deletions src/GitHub.VisualStudio/Commands/OpenFromUrlCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ namespace GitHub.VisualStudio.Commands
public class OpenFromUrlCommand : VsCommand<string>, IOpenFromUrlCommand
{
readonly Lazy<IDialogService> dialogService;
readonly Lazy<IGitHubContextService> gitHubContextService;
readonly Lazy<IRepositoryCloneService> repositoryCloneService;

/// <summary>
Expand All @@ -27,12 +26,10 @@ public class OpenFromUrlCommand : VsCommand<string>, IOpenFromUrlCommand
[ImportingConstructor]
public OpenFromUrlCommand(
Lazy<IDialogService> dialogService,
Lazy<IGitHubContextService> gitHubContextService,
Lazy<IRepositoryCloneService> repositoryCloneService) :
base(CommandSet, CommandId)
{
this.dialogService = dialogService;
this.gitHubContextService = gitHubContextService;
this.repositoryCloneService = repositoryCloneService;

// See https://code.msdn.microsoft.com/windowsdesktop/AllowParams-2005-9442298f
Expand All @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,8 +498,9 @@ static GitHubContextService CreateGitHubContextService(string repositoryDir = nu
{
var sp = Substitute.For<IGitHubServiceProvider>();
var gitService = Substitute.For<IGitService>();
var vsServices = Substitute.For<IVSServices>();
gitService.GetRepository(repositoryDir).Returns(repository);

return new GitHubContextService(sp, gitService);
return new GitHubContextService(sp, gitService, vsServices);
}
}
Loading