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

Commit 7114209

Browse files
authored
Merge branch 'master' into master
2 parents 0c57154 + dd19d59 commit 7114209

File tree

24 files changed

+215
-81
lines changed

24 files changed

+215
-81
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Most of the extension UI lives in the Team Explorer pane, which is available fro
1818
Official builds of this extension are available at [the official website](https://visualstudio.github.com).
1919

2020
[![Build status](https://ci.appveyor.com/api/projects/status/dl8is5iqwt9qf3t7/branch/master?svg=true)](https://ci.appveyor.com/project/github-windows/visualstudio/branch/master)
21+
[![Build Status](https://github-editor-tools.visualstudio.com/VisualStudio/_apis/build/status/github.VisualStudio?branchName=master)](https://github-editor-tools.visualstudio.com/VisualStudio/_build/latest?definitionId=4&branchName=master)
2122
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/github-visual-studio/localized.svg)](https://crowdin.com/project/github-visual-studio)
2223
[![codecov](https://codecov.io/gh/GitHub/VisualStudio/branch/master/graph/badge.svg)](https://codecov.io/gh/GitHub/VisualStudio)
2324

scripts/modules.ps1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ New-Module -ScriptBlock {
115115
}
116116

117117
function Build-Solution([string]$solution, [string]$target, [string]$configuration, [switch]$ForVSInstaller, [bool]$Deploy = $false) {
118-
Run-Command -Fatal { & $nuget restore $solution -NonInteractive -Verbosity detailed }
118+
$msbuild = Find-MSBuild
119+
120+
Run-Command -Fatal { & $nuget restore $solution -NonInteractive -Verbosity detailed -MSBuildPath (Split-Path -parent $msbuild) }
119121
$flag1 = ""
120122
$flag2 = ""
121123
if ($ForVSInstaller) {
@@ -127,8 +129,6 @@ New-Module -ScriptBlock {
127129
$flag1 = "/p:Package=Skip"
128130
}
129131

130-
$msbuild = Find-MSBuild
131-
132132
Write-Host "$msbuild $solution /target:$target /property:Configuration=$configuration /p:DeployExtension=false /verbosity:minimal /p:VisualStudioVersion=15.0 /bl:output.binlog $flag1 $flag2"
133133
Run-Command -Fatal { & $msbuild $solution /target:$target /property:Configuration=$configuration /p:DeployExtension=false /verbosity:minimal /p:VisualStudioVersion=15.0 /bl:output.binlog $flag1 $flag2 }
134134
}

src/GitHub.App/Services/DialogService.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,31 @@ public class DialogService : IDialogService
1616
{
1717
readonly IViewViewModelFactory factory;
1818
readonly IShowDialogService showDialog;
19+
readonly IGitHubContextService gitHubContextService;
1920

2021
[ImportingConstructor]
2122
public DialogService(
2223
IViewViewModelFactory factory,
23-
IShowDialogService showDialog)
24+
IShowDialogService showDialog,
25+
IGitHubContextService gitHubContextService)
2426
{
2527
Guard.ArgumentNotNull(factory, nameof(factory));
2628
Guard.ArgumentNotNull(showDialog, nameof(showDialog));
29+
Guard.ArgumentNotNull(showDialog, nameof(gitHubContextService));
2730

2831
this.factory = factory;
2932
this.showDialog = showDialog;
33+
this.gitHubContextService = gitHubContextService;
3034
}
3135

3236
public async Task<CloneDialogResult> ShowCloneDialog(IConnection connection, string url = null)
3337
{
38+
if (string.IsNullOrEmpty(url))
39+
{
40+
var clipboardContext = gitHubContextService.FindContextFromClipboard();
41+
url = clipboardContext?.Url;
42+
}
43+
3444
var viewModel = factory.CreateViewModel<IRepositoryCloneViewModel>();
3545
if (url != null)
3646
{

src/GitHub.App/Services/GitHubContextService.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Text;
44
using System.Linq;
55
using System.Windows;
6+
using System.Globalization;
67
using System.Threading.Tasks;
78
using System.Collections.Generic;
89
using System.ComponentModel.Composition;
@@ -25,6 +26,7 @@ public class GitHubContextService : IGitHubContextService
2526
{
2627
readonly IGitHubServiceProvider serviceProvider;
2728
readonly IGitService gitService;
29+
readonly IVSServices vsServices;
2830
readonly Lazy<IVsTextManager2> textManager;
2931

3032
// USERID_REGEX = /[a-z0-9][a-z0-9\-\_]*/i
@@ -61,13 +63,38 @@ public class GitHubContextService : IGitHubContextService
6163
static readonly Regex tempFileObjectishRegex = new Regex(@"\\TFSTemp\\[^\\]*[.](?<objectish>[a-z0-9]{8})[.][^.\\]*$", RegexOptions.Compiled);
6264

6365
[ImportingConstructor]
64-
public GitHubContextService(IGitHubServiceProvider serviceProvider, IGitService gitService)
66+
public GitHubContextService(IGitHubServiceProvider serviceProvider, IGitService gitService, IVSServices vsServices)
6567
{
6668
this.serviceProvider = serviceProvider;
6769
this.gitService = gitService;
70+
this.vsServices = vsServices;
6871
textManager = new Lazy<IVsTextManager2>(() => serviceProvider.GetService<SVsTextManager, IVsTextManager2>());
6972
}
7073

74+
/// <inheritdoc/>
75+
public void TryNavigateToContext(string repositoryDir, GitHubContext context)
76+
{
77+
if (context?.LinkType == LinkType.Blob)
78+
{
79+
var (commitish, path, commitSha) = ResolveBlob(repositoryDir, context);
80+
if (commitish == null && path == null)
81+
{
82+
var message = string.Format(CultureInfo.CurrentCulture, Resources.CouldntFindCorrespondingFile, context.Url);
83+
vsServices.ShowMessageBoxInfo(message);
84+
return;
85+
}
86+
87+
var hasChanges = HasChangesInWorkingDirectory(repositoryDir, commitish, path);
88+
if (hasChanges)
89+
{
90+
var message = string.Format(CultureInfo.CurrentCulture, Resources.ChangesInWorkingDirectoryMessage, commitish);
91+
vsServices.ShowMessageBoxInfo(message);
92+
}
93+
94+
TryOpenFile(repositoryDir, context);
95+
}
96+
}
97+
7198
/// <inheritdoc/>
7299
public GitHubContext FindContextFromClipboard()
73100
{

src/GitHub.App/Services/PullRequestEditorService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,13 +298,13 @@ public Task<IDifferenceViewer> OpenDiff(
298298
}
299299

300300
/// <inheritdoc/>
301-
public async Task<IDifferenceViewer> OpenDiff(IPullRequestSession session, string relativePath, string headSha, int fromLine)
301+
public async Task<IDifferenceViewer> OpenDiff(IPullRequestSession session, string relativePath, string headSha, int nextInlineTagFromLine)
302302
{
303303
var diffViewer = await OpenDiff(session, relativePath, headSha, scrollToFirstDraftOrDiff: false);
304304

305305
var param = (object) new InlineCommentNavigationParams
306306
{
307-
FromLine = fromLine,
307+
FromLine = nextInlineTagFromLine,
308308
};
309309

310310
// HACK: We need to wait here for the inline comment tags to initialize so we can find the next inline comment.

src/GitHub.App/Services/RepositoryCloneService.cs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ public class RepositoryCloneService : IRepositoryCloneService
3636
readonly IVSGitServices vsGitServices;
3737
readonly ITeamExplorerServices teamExplorerServices;
3838
readonly IGraphQLClientFactory graphqlFactory;
39+
readonly IGitHubContextService gitHubContextService;
3940
readonly IUsageTracker usageTracker;
41+
readonly Lazy<EnvDTE.DTE> dte;
4042
ICompiledQuery<ViewerRepositoriesModel> readViewerRepositories;
4143

4244
[ImportingConstructor]
@@ -45,13 +47,17 @@ public RepositoryCloneService(
4547
IVSGitServices vsGitServices,
4648
ITeamExplorerServices teamExplorerServices,
4749
IGraphQLClientFactory graphqlFactory,
48-
IUsageTracker usageTracker)
50+
IGitHubContextService gitHubContextService,
51+
IUsageTracker usageTracker,
52+
IGitHubServiceProvider sp)
4953
{
5054
this.operatingSystem = operatingSystem;
5155
this.vsGitServices = vsGitServices;
5256
this.teamExplorerServices = teamExplorerServices;
5357
this.graphqlFactory = graphqlFactory;
58+
this.gitHubContextService = gitHubContextService;
5459
this.usageTracker = usageTracker;
60+
dte = new Lazy<EnvDTE.DTE>(() => sp.GetService<EnvDTE.DTE>());
5561

5662
defaultClonePath = GetLocalClonePathFromGitProvider(operatingSystem.Environment.GetUserRepositoriesPath());
5763
}
@@ -125,7 +131,10 @@ public async Task CloneOrOpenRepository(
125131
var isDotCom = HostAddress.IsGitHubDotComUri(repositoryUrl);
126132
if (DestinationDirectoryExists(repositoryPath))
127133
{
128-
teamExplorerServices.OpenRepository(repositoryPath);
134+
if (!IsSolutionInRepository(repositoryPath))
135+
{
136+
teamExplorerServices.OpenRepository(repositoryPath);
137+
}
129138

130139
if (isDotCom)
131140
{
@@ -153,6 +162,36 @@ public async Task CloneOrOpenRepository(
153162

154163
// Give user a chance to choose a solution
155164
teamExplorerServices.ShowHomePage();
165+
166+
// Navigate to context for supported URL types (e.g. /blob/ URLs)
167+
var context = gitHubContextService.FindContextFromUrl(url);
168+
if (context != null)
169+
{
170+
gitHubContextService.TryNavigateToContext(repositoryPath, context);
171+
}
172+
}
173+
174+
bool IsSolutionInRepository(string repositoryPath)
175+
{
176+
var solutionPath = dte.Value.Solution.FileName;
177+
if (string.IsNullOrEmpty(solutionPath))
178+
{
179+
return false;
180+
}
181+
182+
var isFolder = operatingSystem.Directory.DirectoryExists(solutionPath);
183+
var solutionDir = isFolder ? solutionPath : Path.GetDirectoryName(solutionPath);
184+
if (string.Equals(repositoryPath, solutionDir, StringComparison.OrdinalIgnoreCase))
185+
{
186+
return true;
187+
}
188+
189+
if (solutionDir.StartsWith(repositoryPath + '\\', StringComparison.OrdinalIgnoreCase))
190+
{
191+
return true;
192+
}
193+
194+
return false;
156195
}
157196

158197
/// <inheritdoc/>

src/GitHub.App/ViewModels/Dialog/Clone/RepositoryCloneViewModel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ public async Task InitializeAsync(IConnection connection)
137137

138138
this.WhenAnyValue(x => x.SelectedTabIndex).Subscribe(x => tabs[x].Activate().Forget());
139139

140-
// Users in group A will see the URL tab by default
141-
if (await IsGroupA().ConfigureAwait(false))
140+
// When a clipboard URL has been set or a user is in group A, show the URL tab by default
141+
if (!string.IsNullOrEmpty(UrlTab.Url) || await IsGroupA().ConfigureAwait(false))
142142
{
143143
SelectedTabIndex = 2;
144144
}

src/GitHub.App/ViewModels/GitHubPane/PullRequestFilesViewModel.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ private async Task OpenFirstAnnotation(IPullRequestEditorService editorService,
8383

8484
if (annotationModel != null)
8585
{
86-
await editorService.OpenDiff(pullRequestSession, file.RelativePath, annotationModel.HeadSha, annotationModel.EndLine);
86+
//AnnotationModel.EndLine is a 1-based number
87+
//EditorService.OpenDiff takes a 0-based line number to start searching AFTER and will open the next tag
88+
var nextInlineCommentFromLine = annotationModel.EndLine - 2;
89+
await editorService.OpenDiff(pullRequestSession, file.RelativePath, annotationModel.HeadSha, nextInlineCommentFromLine);
8790
}
8891
}
8992

@@ -247,7 +250,7 @@ async Task<InlineAnnotationModel> GetFirstAnnotation(IPullRequestFileNode file,
247250
var sessionFile = await pullRequestSession.GetFile(file.RelativePath);
248251
var annotations = sessionFile.InlineAnnotations;
249252

250-
return annotations.FirstOrDefault(model => model.AnnotationLevel == annotationLevel);
253+
return annotations.OrderBy(model => model.EndLine).FirstOrDefault(model => model.AnnotationLevel == annotationLevel);
251254
}
252255

253256
/// <summary>

src/GitHub.Exports.Reactive/Models/InlineAnnotationModel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ public InlineAnnotationModel(CheckSuiteModel checkSuite, CheckRunModel checkRun,
3535
public string Path => annotation.Path;
3636

3737
/// <summary>
38-
/// Gets the start line of the annotation.
38+
/// Gets the 1-based start line of the annotation.
3939
/// </summary>
4040
public int StartLine => annotation.StartLine;
4141

4242
/// <summary>
43-
/// Gets the end line of the annotation.
43+
/// Gets the 1-based end line of the annotation.
4444
/// </summary>
4545
public int EndLine => annotation.EndLine;
4646

src/GitHub.Exports.Reactive/Services/IPullRequestEditorService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ public interface IPullRequestEditorService
5555
/// The commit SHA of the right hand side of the diff. Pass null to compare with the
5656
/// working directory, or "HEAD" to compare with the HEAD commit of the pull request.
5757
/// </param>
58-
/// <param name="fromLine">The line number to open</param>
58+
/// <param name="nextInlineTagFromLine">The 0-based line number to execute NextInlineCommentCommand from</param>
5959
/// <returns>The opened diff viewer.</returns>
60-
Task<IDifferenceViewer> OpenDiff(IPullRequestSession session, string relativePath, string headSha, int fromLine);
60+
Task<IDifferenceViewer> OpenDiff(IPullRequestSession session, string relativePath, string headSha, int nextInlineTagFromLine);
6161

6262
/// <summary>
6363
/// Find the active text view.

0 commit comments

Comments
 (0)