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

Commit 8374b58

Browse files
authored
Merge pull request #2128 from BertanAygun/StaticReviewFileMap
Static review file map contract implementation
2 parents 4d1010b + 60389dd commit 8374b58

File tree

3 files changed

+96
-4
lines changed

3 files changed

+96
-4
lines changed

src/GitHub.App/GitHub.App.csproj

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,18 @@
4646
<PackageReference Include="LibGit2Sharp.NativeBinaries" Version="1.0.164" />
4747
<PackageReference Include="Madskristensen.VisualStudio.SDK" Version="14.3.75-pre" />
4848
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.1" />
49+
<PackageReference Include="Microsoft.VisualStudio.StaticReviews.Embeddable" Version="0.1.14-alpha" />
4950
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
5051
<PackageReference Include="Rothko" Version="0.0.3-ghfvs" />
5152
<PackageReference Include="Serilog" Version="2.5.0" />
5253
<PackageReference Include="SerilogAnalyzer" Version="0.12.0.0" />
5354
<PackageReference Include="Stateless" Version="2.5.56.0" targetFramework="net45" />
5455
</ItemGroup>
55-
</Project>
56+
<Target Name="LinkStaticReviewsEmbeddableAssemblies" AfterTargets="ResolveReferences" BeforeTargets="FindReferenceAssembliesForReferences">
57+
<ItemGroup>
58+
<ReferencePath Condition="'%(FileName)' == 'Microsoft.VisualStudio.StaticReviews.Embeddable'">
59+
<EmbedInteropTypes>true</EmbedInteropTypes>
60+
</ReferencePath>
61+
</ItemGroup>
62+
</Target>
63+
</Project>

src/GitHub.App/Services/PullRequestService.cs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
using System.Reactive;
99
using System.Reactive.Linq;
1010
using System.Reactive.Threading.Tasks;
11+
using System.Runtime.InteropServices;
1112
using System.Text;
1213
using System.Text.RegularExpressions;
14+
using System.Threading;
1315
using System.Threading.Tasks;
1416
using System.Windows.Forms;
1517
using GitHub.Api;
@@ -19,6 +21,7 @@
1921
using GitHub.Models;
2022
using GitHub.Primitives;
2123
using LibGit2Sharp;
24+
using Microsoft.VisualStudio.StaticReviews.Contracts;
2225
using Octokit.GraphQL;
2326
using Octokit.GraphQL.Model;
2427
using Rothko;
@@ -32,7 +35,7 @@ namespace GitHub.Services
3235
{
3336
[Export(typeof(IPullRequestService))]
3437
[PartCreationPolicy(CreationPolicy.Shared)]
35-
public class PullRequestService : IPullRequestService
38+
public class PullRequestService : IPullRequestService, IStaticReviewFileMap
3639
{
3740
const string SettingCreatedByGHfVS = "created-by-ghfvs";
3841
const string SettingGHfVSPullRequest = "ghfvs-pr-owner-number";
@@ -58,6 +61,8 @@ public class PullRequestService : IPullRequestService
5861
readonly IOperatingSystem os;
5962
readonly IUsageTracker usageTracker;
6063

64+
readonly IDictionary<string, (string commitId, string repoPath)> tempFileMappings;
65+
6166
[ImportingConstructor]
6267
public PullRequestService(
6368
IGitClient gitClient,
@@ -73,6 +78,7 @@ public PullRequestService(
7378
this.graphqlFactory = graphqlFactory;
7479
this.os = os;
7580
this.usageTracker = usageTracker;
81+
this.tempFileMappings = new Dictionary<string, (string commitId, string repoPath)>(StringComparer.OrdinalIgnoreCase);
7682
}
7783

7884
public async Task<Page<PullRequestListItemModel>> ReadPullRequests(
@@ -755,6 +761,12 @@ public async Task<string> ExtractToTempFile(
755761
}
756762
}
757763

764+
lock (this.tempFileMappings)
765+
{
766+
string gitRelativePath = relativePath.TrimStart('/').Replace('\\', '/');
767+
this.tempFileMappings[CanonicalizeLocalFilePath(tempFilePath)] = (commitSha, gitRelativePath);
768+
}
769+
758770
return tempFilePath;
759771
}
760772

@@ -827,6 +839,28 @@ public bool ConfirmCancelPendingReview()
827839
MessageBoxIcon.Question) == DialogResult.Yes;
828840
}
829841

842+
/// <inheritdoc />
843+
public Task<string> GetObjectishFromLocalPathAsync(string localPath, CancellationToken cancellationToken)
844+
{
845+
lock (this.tempFileMappings)
846+
{
847+
var canonicalizedPath = CanonicalizeLocalFilePath(localPath);
848+
if (this.tempFileMappings.TryGetValue(canonicalizedPath, out (string commitId, string repoPath) result))
849+
{
850+
return Task.FromResult($"{result.commitId}:{result.repoPath}");
851+
}
852+
}
853+
854+
return Task.FromResult<string>(null);
855+
}
856+
857+
/// <inheritdoc />
858+
public Task<string> GetLocalPathFromObjectishAsync(string objectish, CancellationToken cancellationToken)
859+
{
860+
throw new NotImplementedException();
861+
}
862+
863+
830864
async Task<string> CreateRemote(IRepository repo, UriString cloneUri)
831865
{
832866
foreach (var remote in repo.Network.Remotes)
@@ -1006,6 +1040,12 @@ static string BuildGHfVSConfigKeyValue(string owner, int number)
10061040
return default;
10071041
}
10081042

1043+
static string CanonicalizeLocalFilePath(string localPath)
1044+
{
1045+
localPath = localPath.Replace("\\\\", "\\");
1046+
return Path.GetFullPath(localPath);
1047+
}
1048+
10091049
class ListItemAdapter : PullRequestListItemModel
10101050
{
10111051
public IList<ReviewAdapter> Reviews { get; set; }

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

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Reactive;
88
using System.Reactive.Linq;
99
using System.Reactive.Threading.Tasks;
10+
using System.Threading;
1011
using System.Threading.Tasks;
1112
using GitHub.App;
1213
using GitHub.Commands;
@@ -17,6 +18,7 @@
1718
using GitHub.Models;
1819
using GitHub.Services;
1920
using LibGit2Sharp;
21+
using Microsoft.VisualStudio.StaticReviews.Contracts;
2022
using ReactiveUI;
2123
using ReactiveUI.Legacy;
2224
using Serilog;
@@ -28,7 +30,7 @@ namespace GitHub.ViewModels.GitHubPane
2830
/// <inheritdoc cref="IPullRequestDetailViewModel"/>
2931
[Export(typeof(IPullRequestDetailViewModel))]
3032
[PartCreationPolicy(CreationPolicy.NonShared)]
31-
public sealed class PullRequestDetailViewModel : PanePageViewModelBase, IPullRequestDetailViewModel
33+
public sealed class PullRequestDetailViewModel : PanePageViewModelBase, IPullRequestDetailViewModel, IStaticReviewFileMap
3234
{
3335
static readonly ILogger log = LogManager.ForContext<PullRequestDetailViewModel>();
3436

@@ -40,6 +42,7 @@ public sealed class PullRequestDetailViewModel : PanePageViewModelBase, IPullReq
4042
readonly ISyncSubmodulesCommand syncSubmodulesCommand;
4143
readonly IViewViewModelFactory viewViewModelFactory;
4244
readonly IGitService gitService;
45+
4346
IModelService modelService;
4447
PullRequestDetailModel model;
4548
IActorViewModel author;
@@ -98,6 +101,7 @@ public PullRequestDetailViewModel(
98101
this.syncSubmodulesCommand = syncSubmodulesCommand;
99102
this.viewViewModelFactory = viewViewModelFactory;
100103
this.gitService = gitService;
104+
101105
Files = files;
102106

103107
Checkout = ReactiveCommand.CreateFromObservable(
@@ -137,6 +141,9 @@ public PullRequestDetailViewModel(
137141
ShowAnnotations = ReactiveCommand.Create<IPullRequestCheckViewModel>(DoShowAnnotations);
138142
}
139143

144+
[Import(AllowDefault = true)]
145+
private IStaticReviewFileMapManager StaticReviewFileMapManager { get; set; }
146+
140147
private void DoOpenDetailsUrl()
141148
{
142149
usageTracker.IncrementCounter(measuresModel => measuresModel.NumberOfPRDetailsOpenInGitHub).Forget();
@@ -490,6 +497,7 @@ public string GetLocalFilePath(IPullRequestFileNode file)
490497
public override void Activated()
491498
{
492499
active = true;
500+
this.StaticReviewFileMapManager?.RegisterStaticReviewFileMap(this);
493501

494502
if (refreshOnActivate)
495503
{
@@ -499,7 +507,43 @@ public override void Activated()
499507
}
500508

501509
/// <inheritdoc/>
502-
public override void Deactivated() => active = false;
510+
public override void Deactivated()
511+
{
512+
this.StaticReviewFileMapManager?.UnregisterStaticReviewFileMap(this);
513+
active = false;
514+
}
515+
516+
/// <inheritdoc/>
517+
public Task<string> GetLocalPathFromObjectishAsync(string objectish, CancellationToken cancellationToken)
518+
{
519+
if (this.pullRequestsService != null)
520+
{
521+
string commitId = objectish.Substring(0, objectish.IndexOf(':'));
522+
string relativePath = objectish.Substring(objectish.IndexOf(':')+1).TrimStart('/');
523+
524+
return this.pullRequestsService.ExtractToTempFile(
525+
this.Session.LocalRepository,
526+
this.Session.PullRequest,
527+
relativePath,
528+
commitId,
529+
this.pullRequestsService.GetEncoding(this.Session.LocalRepository, relativePath));
530+
}
531+
532+
return Task.FromResult<string>(null);
533+
}
534+
535+
/// <inheritdoc/>
536+
public Task<string> GetObjectishFromLocalPathAsync(string localPath, CancellationToken cancellationToken)
537+
{
538+
// We rely on pull request service's global map here instead of trying to get it from IPullRequestSessionManager via ITextBuffer
539+
// because it is possible that the file queried wasn't opened by GitHub extension and instead was opened by LSP
540+
if (this.pullRequestsService is IStaticReviewFileMap staticReviewFileMap)
541+
{
542+
return staticReviewFileMap.GetObjectishFromLocalPathAsync(localPath, cancellationToken);
543+
}
544+
545+
return Task.FromResult<string>(null);
546+
}
503547

504548
/// <inheritdoc/>
505549
protected override void Dispose(bool disposing)

0 commit comments

Comments
 (0)