Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit c429d76

Browse files
committed
Show dialog when attempting to open non-blob URL
"Couldn't open from 'https://github.com/owner/name'. Only URLs that link to repository files are currently supported."
1 parent fd0f835 commit c429d76

File tree

6 files changed

+84
-14
lines changed

6 files changed

+84
-14
lines changed

src/GitHub.App/Services/GitHubContextService.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.ComponentModel.Composition;
99
using System.Text.RegularExpressions;
1010
using System.Runtime.InteropServices;
11+
using GitHub.Exports;
1112
using GitHub.Services;
1213
using GitHub.Extensions;
1314
using GitHub.Primitives;
@@ -90,6 +91,7 @@ public GitHubContext FindContextFromUrl(string url)
9091
Host = uri.Host,
9192
Owner = uri.Owner,
9293
RepositoryName = uri.RepositoryName,
94+
Url = uri
9395
};
9496

9597
var repositoryPrefix = uri.ToRepositoryUrl().ToString() + "/";
@@ -109,6 +111,7 @@ public GitHubContext FindContextFromUrl(string url)
109111
{
110112
context.TreeishPath = match.Groups["treeish"].Value;
111113
context.BlobName = match.Groups["blobName"].Value;
114+
context.LinkType = LinkType.Blob;
112115
return context;
113116
}
114117

src/GitHub.Exports/Exports/ExportMetadata.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public enum MenuType
1919
/// </summary>
2020
public enum LinkType
2121
{
22+
Unknown,
2223
Blob,
2324
Blame
2425
}

src/GitHub.Exports/Services/GitHubContext.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
namespace GitHub.Services
1+
using GitHub.Exports;
2+
using GitHub.Primitives;
3+
4+
namespace GitHub.Services
25
{
36
public class GitHubContext
47
{
@@ -15,5 +18,7 @@ public class GitHubContext
1518
public int? Issue { get; set; }
1619
public int? Line { get; set; }
1720
public int? LineEnd { get; set; }
21+
public UriString Url { get; set; }
22+
public LinkType LinkType { get; set; }
1823
}
1924
}

src/GitHub.VisualStudio/Commands/OpenFromClipboardCommand.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.ComponentModel.Composition;
33
using GitHub.Commands;
4+
using GitHub.Exports;
45
using GitHub.Services;
56
using GitHub.Services.Vssdk.Commands;
67
using Task = System.Threading.Tasks.Task;
@@ -16,6 +17,7 @@ public class OpenFromClipboardCommand : VsCommand<string>, IOpenFromClipboardCom
1617
public const string NoActiveRepositoryMessage = "There is no active repository to navigate";
1718
public const string ChangesInWorkingDirectoryMessage = "This file has changed since the permalink was created";
1819
public const string DifferentRepositoryMessage = "Please open the repository '{0}' and try again";
20+
public const string UnknownLinkTypeMessage = "Couldn't open from '{0}'. Only URLs that link to repository files are currently supported.";
1921

2022
readonly Lazy<IGitHubContextService> gitHubContextService;
2123
readonly Lazy<ITeamExplorerContext> teamExplorerContext;
@@ -55,6 +57,13 @@ public override async Task Execute(string url)
5557
return;
5658
}
5759

60+
if (context.LinkType != LinkType.Blob)
61+
{
62+
var message = string.Format(UnknownLinkTypeMessage, context.Url);
63+
vsServices.Value.ShowMessageBoxInfo(message);
64+
return;
65+
}
66+
5867
var activeRepository = teamExplorerContext.Value.ActiveRepository;
5968
var repositoryDir = activeRepository?.LocalPath;
6069
if (repositoryDir == null)

test/GitHub.App.UnitTests/Services/GitHubContextServiceTests.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using GitHub.Exports;
23
using GitHub.Services;
34
using GitHub.App.Services;
45
using NSubstitute;
@@ -121,6 +122,27 @@ public void IsNull(string url, bool expectNull)
121122

122123
Assert.That(context, expectNull ? Is.Null : Is.Not.Null);
123124
}
125+
126+
[TestCase("https://github.com/github/VisualStudio/blob/master/README.md", "https://github.com/github/VisualStudio/blob/master/README.md")]
127+
public void Url_EqualTo(string url, string expectUrl)
128+
{
129+
var target = CreateGitHubContextService();
130+
131+
var context = target.FindContextFromUrl(url);
132+
133+
Assert.That(context.Url?.ToString(), Is.EqualTo(expectUrl));
134+
}
135+
136+
[TestCase("https://github.com/github/VisualStudio/blob/master/README.md", LinkType.Blob)]
137+
[TestCase("https://github.com/github/VisualStudio/unknown/master/README.md", LinkType.Unknown)]
138+
public void LinkType_EqualTo(string url, LinkType expectLinkType)
139+
{
140+
var target = CreateGitHubContextService();
141+
142+
var context = target.FindContextFromUrl(url);
143+
144+
Assert.That(context.LinkType, Is.EqualTo(expectLinkType));
145+
}
124146
}
125147

126148
public class TheToMethod

test/GitHub.VisualStudio.UnitTests/Commands/OpenFromClipboardCommandTests.cs

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using System;
22
using System.Threading.Tasks;
3+
using GitHub.Exports;
4+
using GitHub.Primitives;
5+
using GitHub.App.Services;
36
using GitHub.Services;
47
using GitHub.VisualStudio.Commands;
58
using Microsoft.VisualStudio;
@@ -25,7 +28,7 @@ public async Task NothingInClipboard()
2528
[Test]
2629
public async Task NoLocalRepository()
2730
{
28-
var context = new GitHubContext();
31+
var context = CreateGitHubContext();
2932
var repositoryDir = null as string;
3033
var vsServices = Substitute.For<IVSServices>();
3134
var target = CreateOpenFromClipboardCommand(vsServices: vsServices, contextFromClipboard: context, repositoryDir: repositoryDir);
@@ -35,13 +38,27 @@ public async Task NoLocalRepository()
3538
vsServices.Received(1).ShowMessageBoxInfo(OpenFromClipboardCommand.NoActiveRepositoryMessage);
3639
}
3740

41+
[Test]
42+
public async Task UnknownLinkType()
43+
{
44+
var context = new GitHubContext { LinkType = LinkType.Unknown };
45+
var expectMessage = string.Format(OpenFromClipboardCommand.UnknownLinkTypeMessage, context.Url);
46+
var activeRepositoryDir = "activeRepositoryDir";
47+
var vsServices = Substitute.For<IVSServices>();
48+
var target = CreateOpenFromClipboardCommand(vsServices: vsServices, contextFromClipboard: context, repositoryDir: activeRepositoryDir);
49+
50+
await target.Execute(null);
51+
52+
vsServices.Received(1).ShowMessageBoxInfo(expectMessage);
53+
}
54+
3855
[TestCase("targetRepositoryName", "activeRepositoryName", OpenFromClipboardCommand.DifferentRepositoryMessage)]
3956
[TestCase("SameRepositoryName", "SameRepositoryName", null)]
4057
[TestCase("same_repository_name", "SAME_REPOSITORY_NAME", null)]
4158
public async Task DifferentLocalRepository(string targetRepositoryName, string activeRepositoryName, string expectMessage)
4259
{
4360
var activeRepositoryDir = "activeRepositoryDir";
44-
var context = new GitHubContext { RepositoryName = targetRepositoryName };
61+
var context = CreateGitHubContext(repositoryName: targetRepositoryName);
4562
var resolveBlobResult = ("commitish", "path", "SHA");
4663
var vsServices = Substitute.For<IVSServices>();
4764
var target = CreateOpenFromClipboardCommand(vsServices: vsServices,
@@ -64,12 +81,13 @@ public async Task DifferentLocalRepository(string targetRepositoryName, string a
6481
[TestCase("sameowner", "SAMEOWNER", OpenFromClipboardCommand.NoResolveSameOwnerMessage)]
6582
public async Task CouldNotResolve(string targetOwner, string currentOwner, string expectMessage)
6683
{
67-
var context = new GitHubContext { Owner = targetOwner };
6884
var repositoryDir = "repositoryDir";
85+
var repositoryName = "repositoryName";
86+
var context = CreateGitHubContext(repositoryName: repositoryName, owner: targetOwner);
6987
(string, string, string)? resolveBlobResult = null;
7088
var vsServices = Substitute.For<IVSServices>();
7189
var target = CreateOpenFromClipboardCommand(vsServices: vsServices,
72-
contextFromClipboard: context, repositoryDir: repositoryDir, repositoryOwner: currentOwner, resolveBlobResult: resolveBlobResult);
90+
contextFromClipboard: context, repositoryDir: repositoryDir, repositoryOwner: currentOwner, repositoryName: repositoryName, resolveBlobResult: resolveBlobResult);
7391

7492
await target.Execute(null);
7593

@@ -79,12 +97,13 @@ public async Task CouldNotResolve(string targetOwner, string currentOwner, strin
7997
[Test]
8098
public async Task CouldResolve()
8199
{
82-
var context = new GitHubContext();
100+
var repositoryName = "repositoryName";
101+
var context = CreateGitHubContext(repositoryName: repositoryName);
83102
var repositoryDir = "repositoryDir";
84103
var resolveBlobResult = ("master", "foo.cs", "");
85104
var vsServices = Substitute.For<IVSServices>();
86105
var target = CreateOpenFromClipboardCommand(vsServices: vsServices,
87-
contextFromClipboard: context, repositoryDir: repositoryDir, resolveBlobResult: resolveBlobResult);
106+
contextFromClipboard: context, repositoryDir: repositoryDir, repositoryName: repositoryName, resolveBlobResult: resolveBlobResult);
88107

89108
await target.Execute(null);
90109

@@ -94,13 +113,14 @@ public async Task CouldResolve()
94113
[Test]
95114
public async Task NoChangesInWorkingDirectory()
96115
{
97-
var gitHubContextService = Substitute.For<IGitHubContextService>();
98-
var context = new GitHubContext();
99116
var repositoryDir = "repositoryDir";
117+
var repositoryName = "repositoryName";
118+
var context = CreateGitHubContext(repositoryName: repositoryName);
119+
var gitHubContextService = Substitute.For<IGitHubContextService>();
100120
var resolveBlobResult = ("master", "foo.cs", "");
101121
var vsServices = Substitute.For<IVSServices>();
102122
var target = CreateOpenFromClipboardCommand(gitHubContextService: gitHubContextService, vsServices: vsServices,
103-
contextFromClipboard: context, repositoryDir: repositoryDir, resolveBlobResult: resolveBlobResult, hasChanges: false);
123+
contextFromClipboard: context, repositoryDir: repositoryDir, repositoryName: repositoryName, resolveBlobResult: resolveBlobResult, hasChanges: false);
104124

105125
await target.Execute(null);
106126

@@ -113,15 +133,17 @@ public async Task NoChangesInWorkingDirectory()
113133
public async Task HasChangesInWorkingDirectory(bool annotateFileSupported, string message,
114134
int receivedTryAnnotateFile, int receivedTryOpenFile)
115135
{
136+
var repositoryDir = "repositoryDir";
137+
var repositoryName = "repositoryName";
138+
var targetBranch = "targetBranch";
139+
var context = CreateGitHubContext(repositoryName: repositoryName, branch: targetBranch);
116140
var gitHubContextService = Substitute.For<IGitHubContextService>();
117141
gitHubContextService.TryAnnotateFile(null, null, null).ReturnsForAnyArgs(annotateFileSupported);
118-
var context = new GitHubContext();
119-
var repositoryDir = "repositoryDir";
120142
var currentBranch = "currentBranch";
121-
var resolveBlobResult = ("master", "foo.cs", "");
143+
var resolveBlobResult = (targetBranch, "foo.cs", "");
122144
var vsServices = Substitute.For<IVSServices>();
123145
var target = CreateOpenFromClipboardCommand(gitHubContextService: gitHubContextService, vsServices: vsServices,
124-
contextFromClipboard: context, repositoryDir: repositoryDir, currentBranch: currentBranch, resolveBlobResult: resolveBlobResult, hasChanges: true);
146+
contextFromClipboard: context, repositoryDir: repositoryDir, repositoryName: repositoryName, currentBranch: currentBranch, resolveBlobResult: resolveBlobResult, hasChanges: true);
125147

126148
await target.Execute(null);
127149

@@ -138,6 +160,14 @@ public async Task HasChangesInWorkingDirectory(bool annotateFileSupported, strin
138160
gitHubContextService.Received(receivedTryOpenFile).TryOpenFile(repositoryDir, context);
139161
}
140162

163+
static GitHubContext CreateGitHubContext(UriString uri = null, string owner = "github", string repositoryName = "VisualStudio"
164+
string branch = "master")
165+
{
166+
uri = uri ?? new UriString($"https://github.com/{owner}/{repositoryName}/blob/{branch}/README.md");
167+
168+
return new GitHubContextService(null, null).FindContextFromUrl(uri);
169+
}
170+
141171
static OpenFromClipboardCommand CreateOpenFromClipboardCommand(
142172
IGitHubContextService gitHubContextService = null,
143173
ITeamExplorerContext teamExplorerContext = null,

0 commit comments

Comments
 (0)