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

Commit dab6911

Browse files
authored
Merge branch 'master' into bump-version
2 parents 5f061c5 + dffdf45 commit dab6911

File tree

7 files changed

+274
-13
lines changed

7 files changed

+274
-13
lines changed

CONTRIBUTING.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@ This project adheres to the [Open Code of Conduct][code-of-conduct]. By particip
1313

1414
## Submitting a pull request
1515

16-
0. [Fork][] and clone the repository (see Build Instructions in the [README][readme])
17-
0. Create a new branch: `git checkout -b my-branch-name`
18-
0. Make your change, add tests, and make sure the tests still pass
19-
0. Push to your fork and [submit a pull request][pr]
20-
0. Pat your self on the back and wait for your pull request to be reviewed and merged.
16+
1. [Fork][] and clone the repository (see Build Instructions in the [README][readme])
17+
2. Create a new branch: `git checkout -b my-branch-name`
18+
3. Make your change, add tests, and make sure the tests still pass
19+
4. Push to your fork and [submit a pull request][pr]
20+
5. Pat your self on the back and wait for your pull request to be reviewed and merged.
2121

2222
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
2323

24-
- Follow the existing code's style.
25-
- Write tests.
24+
- Follow the style/format of the existing code.
25+
- Write tests for your changes.
2626
- Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests.
2727
- Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
2828

@@ -38,7 +38,7 @@ There are certain areas of the extension that are restricted in what they can do
3838
### Bug Reporting
3939

4040
Here are a few helpful tips when reporting a bug:
41-
- Verify the bug resides in the GitHub for Visual Studio extension
41+
- Verify that the bug resides in the GitHub for Visual Studio extension
4242
- A lot of functionality provided by this extension resides in the Team Explorer pane, alongside other non-GitHub tools to manage and collaborate on source code, including Visual Studio's Git support, which is owned by Microsoft.
4343
- If this bug not is related to the GitHub extension, visit the [Visual Studio support page](https://www.visualstudio.com/support/support-overview-vs) for help
4444
- Screenshots are very helpful in diagnosing bugs and understanding the state of the extension when it's experiencing problems. Please include them whenever possible.

src/GitHub.App/Services/GitHubContextService.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public class GitHubContextService : IGitHubContextService
5858
static readonly Regex treeishCommitRegex = new Regex($"(?<commit>[a-z0-9]{{40}})(/(?<tree>.+))?", RegexOptions.Compiled);
5959
static readonly Regex treeishBranchRegex = new Regex($"(?<branch>master)(/(?<tree>.+))?", RegexOptions.Compiled);
6060

61+
static readonly Regex tempFileObjectishRegex = new Regex(@"\\TFSTemp\\[^\\]*[.](?<objectish>[a-z0-9]{8})[.][^.\\]*$", RegexOptions.Compiled);
62+
6163
[ImportingConstructor]
6264
public GitHubContextService(IGitHubServiceProvider serviceProvider, IGitService gitService)
6365
{
@@ -305,6 +307,55 @@ public bool TryOpenFile(string repositoryDir, GitHubContext context)
305307
}
306308
}
307309

310+
/// <inheritdoc/>
311+
public string FindObjectishForTFSTempFile(string tempFile)
312+
{
313+
var match = tempFileObjectishRegex.Match(tempFile);
314+
if (match.Success)
315+
{
316+
return match.Groups["objectish"].Value;
317+
}
318+
319+
return null;
320+
}
321+
322+
/// <inheritdoc/>
323+
public (string commitSha, string blobPath) ResolveBlobFromHistory(string repositoryDir, string objectish)
324+
{
325+
using (var repo = gitService.GetRepository(repositoryDir))
326+
{
327+
var blob = repo.Lookup<Blob>(objectish);
328+
if (blob == null)
329+
{
330+
return (null, null);
331+
}
332+
333+
foreach (var commit in repo.Commits)
334+
{
335+
var trees = new Stack<Tree>();
336+
trees.Push(commit.Tree);
337+
338+
while (trees.Count > 0)
339+
{
340+
foreach (var treeEntry in trees.Pop())
341+
{
342+
if (treeEntry.Target == blob)
343+
{
344+
return (commit.Sha, treeEntry.Path);
345+
}
346+
347+
if (treeEntry.TargetType == TreeEntryTargetType.Tree)
348+
{
349+
trees.Push((Tree)treeEntry.Target);
350+
}
351+
}
352+
}
353+
}
354+
355+
return (null, null);
356+
}
357+
}
358+
308359
/// <inheritdoc/>
309360
public bool HasChangesInWorkingDirectory(string repositoryDir, string commitish, string path)
310361
{

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,7 @@ void FilterChanged()
246246
{
247247
numberFilter = 0;
248248

249-
if (SearchQuery.StartsWith('#'))
250-
{
251-
int.TryParse(SearchQuery.Substring(1), out numberFilter);
252-
}
249+
int.TryParse(SearchQuery.Substring(SearchQuery.StartsWith('#') ? 1 : 0), out numberFilter);
253250

254251
if (numberFilter == 0)
255252
{

src/GitHub.Exports/Services/IGitHubContextService.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,30 @@ public interface IGitHubContextService
7171
/// <returns>The resolved commit-ish, blob path and commit SHA for the blob. Path will be null if the commit-ish can be resolved but not the blob.</returns>
7272
(string commitish, string path, string commitSha) ResolveBlob(string repositoryDir, GitHubContext context, string remoteName = "origin");
7373

74+
/// <summary>
75+
/// Find the object-ish (first 8 chars of a blob SHA) from the path to historical blob created by Team Explorer.
76+
/// </summary>
77+
/// <remarks>
78+
/// Team Explorer creates temporary blob files in the following format:
79+
/// C:\Users\me\AppData\Local\Temp\TFSTemp\vctmp21996_181282.IOpenFromClipboardCommand.783ac965.cs
80+
/// The object-ish appears immediately before the file extension and the path contains the folder "TFSTemp".
81+
/// <remarks>
82+
/// <param name="tempFile">The path to a possible Team Explorer temporary blob file.</param>
83+
/// <returns>The target file's object-ish (blob SHA fragment) or null if the path isn't recognized as a Team Explorer blob file.</returns>
84+
string FindObjectishForTFSTempFile(string tempFile);
85+
86+
/// <summary>
87+
/// Find a tree entry in the commit log where a blob appears and return its commit SHA and path.
88+
/// </summary>
89+
/// <remarks>
90+
/// Search back through the commit log for the first tree entry where a blob appears. This operation only takes
91+
/// a fraction of a seond on the `github/VisualStudio` repository even if a tree entry casn't be found.
92+
/// </remarks>
93+
/// <param name="repositoryDir">The target repository directory.</param>
94+
/// <param name="objectish">The fragment of a blob SHA to find.</param>
95+
/// <returns>The commit SHA and blob path or null if the blob can't be found.</returns>
96+
(string commitSha, string blobPath) ResolveBlobFromHistory(string repositoryDir, string objectish);
97+
7498
/// <summary>
7599
/// Check if a file in the working directory has changed since a specified commit-ish.
76100
/// </summary>

src/GitHub.InlineReviews/Views/CommentView.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
Height="16"
5757
Account="{Binding Author}"/>
5858

59-
<TextBlock Foreground="{DynamicResource GitHubVsToolWindowText}" FontWeight="Bold" Text="{Binding User.Login}" Margin="4 0"/>
59+
<TextBlock Foreground="{DynamicResource GitHubVsToolWindowText}" FontWeight="Bold" Text="{Binding Author.Login}" Margin="4 0"/>
6060
<ui:GitHubActionLink Content="{Binding UpdatedAt, Converter={ui:DurationToStringConverter}}"
6161
Command="{Binding OpenOnGitHub}"
6262
Foreground="{DynamicResource GitHubVsToolWindowText}"

src/GitHub.VisualStudio/Commands/GoToSolutionOrPullRequestFileCommand.cs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.IO;
23
using System.ComponentModel.Composition;
34
using GitHub.Services;
45
using GitHub.Extensions;
@@ -10,6 +11,7 @@
1011
using Microsoft.VisualStudio.Shell.Interop;
1112
using Microsoft.VisualStudio.Text.Editor;
1213
using Microsoft.VisualStudio.Text.Differencing;
14+
using Microsoft.VisualStudio.TextManager.Interop;
1315
using Task = System.Threading.Tasks.Task;
1416

1517
namespace GitHub.Commands
@@ -40,6 +42,8 @@ public class GoToSolutionOrPullRequestFileCommand : VsCommand, IGoToSolutionOrPu
4042
readonly Lazy<IVsEditorAdaptersFactoryService> editorAdapter;
4143
readonly Lazy<IPullRequestSessionManager> sessionManager;
4244
readonly Lazy<IPullRequestEditorService> pullRequestEditorService;
45+
readonly Lazy<ITeamExplorerContext> teamExplorerContext;
46+
readonly Lazy<IGitHubContextService> gitHubContextService;
4347
readonly Lazy<IStatusBarNotificationService> statusBar;
4448
readonly Lazy<IUsageTracker> usageTracker;
4549

@@ -49,13 +53,17 @@ public GoToSolutionOrPullRequestFileCommand(
4953
Lazy<IVsEditorAdaptersFactoryService> editorAdapter,
5054
Lazy<IPullRequestSessionManager> sessionManager,
5155
Lazy<IPullRequestEditorService> pullRequestEditorService,
56+
Lazy<ITeamExplorerContext> teamExplorerContext,
57+
Lazy<IGitHubContextService> gitHubContextService,
5258
Lazy<IStatusBarNotificationService> statusBar,
5359
Lazy<IUsageTracker> usageTracker) : base(CommandSet, CommandId)
5460
{
5561
this.serviceProvider = serviceProvider;
5662
this.editorAdapter = editorAdapter;
5763
this.sessionManager = sessionManager;
5864
this.pullRequestEditorService = pullRequestEditorService;
65+
this.gitHubContextService = gitHubContextService;
66+
this.teamExplorerContext = teamExplorerContext;
5967
this.statusBar = statusBar;
6068
this.usageTracker = usageTracker;
6169

@@ -112,6 +120,11 @@ public override async Task Execute()
112120
return;
113121
}
114122

123+
if (TryNavigateFromHistoryFile(sourceView))
124+
{
125+
return;
126+
}
127+
115128
var relativePath = sessionManager.Value.GetRelativePath(textView.TextBuffer);
116129
if (relativePath == null)
117130
{
@@ -189,6 +202,11 @@ void OnBeforeQueryStatus(object sender, EventArgs e)
189202
return;
190203
}
191204
}
205+
206+
if (TryNavigateFromHistoryFileQueryStatus(sourceView))
207+
{
208+
return;
209+
}
192210
}
193211
catch (Exception ex)
194212
{
@@ -198,6 +216,65 @@ void OnBeforeQueryStatus(object sender, EventArgs e)
198216
Visible = false;
199217
}
200218

219+
// Set command Text/Visible properties and return true when active
220+
bool TryNavigateFromHistoryFileQueryStatus(IVsTextView sourceView)
221+
{
222+
if (teamExplorerContext.Value.ActiveRepository?.LocalPath is string && // Check there is an active repo
223+
FindObjectishForTFSTempFile(sourceView) is string) // Looks like a history file
224+
{
225+
// Navigate from history file is active
226+
Text = "Open File in Solution";
227+
Visible = true;
228+
return true;
229+
}
230+
231+
return false;
232+
}
233+
234+
// Attempt navigation to historical file
235+
bool TryNavigateFromHistoryFile(IVsTextView sourceView)
236+
{
237+
if (teamExplorerContext.Value.ActiveRepository?.LocalPath is string repositoryDir &&
238+
FindObjectishForTFSTempFile(sourceView) is string objectish)
239+
{
240+
var (commitSha, blobPath) = gitHubContextService.Value.ResolveBlobFromHistory(repositoryDir, objectish);
241+
if (blobPath is string)
242+
{
243+
var workingFile = Path.Combine(repositoryDir, blobPath);
244+
VsShellUtilities.OpenDocument(serviceProvider, workingFile, VSConstants.LOGVIEWID.TextView_guid,
245+
out IVsUIHierarchy hierarchy, out uint itemID, out IVsWindowFrame windowFrame, out IVsTextView targetView);
246+
247+
pullRequestEditorService.Value.NavigateToEquivalentPosition(sourceView, targetView);
248+
return true;
249+
}
250+
}
251+
252+
return false;
253+
}
254+
255+
// Find the blob SHA in a file name if any
256+
string FindObjectishForTFSTempFile(IVsTextView sourceView)
257+
{
258+
return
259+
FindPath(sourceView) is string path &&
260+
gitHubContextService.Value.FindObjectishForTFSTempFile(path) is string objectish ?
261+
objectish : null;
262+
}
263+
264+
// See http://microsoft.public.vstudio.extensibility.narkive.com/agfoD1GO/full-pathname-of-file-shown-in-current-view-of-core-editor#post2
265+
static string FindPath(IVsTextView textView)
266+
{
267+
ErrorHandler.ThrowOnFailure(textView.GetBuffer(out IVsTextLines buffer));
268+
var userData = buffer as IVsUserData;
269+
if (userData == null)
270+
{
271+
return null;
272+
}
273+
274+
ErrorHandler.ThrowOnFailure(userData.GetData(typeof(IVsUserData).GUID, out object data));
275+
return data as string;
276+
}
277+
201278
ITextView FindActiveTextView(IDifferenceViewer diffViewer)
202279
{
203280
switch (diffViewer.ActiveViewType)

0 commit comments

Comments
 (0)