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

Commit

Permalink
Merge branch 'master' into stanley/check-suites-pull-request-model-1
Browse files Browse the repository at this point in the history
  • Loading branch information
StanleyGoldman committed Aug 7, 2018
2 parents f964972 + ab7ec8b commit 14d5eca
Show file tree
Hide file tree
Showing 15 changed files with 213 additions and 67 deletions.
4 changes: 2 additions & 2 deletions src/GitHub.App/Services/PullRequestService.cs
Expand Up @@ -439,7 +439,7 @@ public IObservable<Unit> Checkout(ILocalRepositoryModel repository, PullRequestD
{
await gitClient.Checkout(repo, localBranchName);
}
else if (repository.CloneUrl.Owner == pullRequest.HeadRepositoryOwner)
else if (string.Equals(repository.CloneUrl.Owner, pullRequest.HeadRepositoryOwner, StringComparison.OrdinalIgnoreCase))
{
var remote = await gitClient.GetHttpRemote(repo, "origin");
await gitClient.Fetch(repo, remote.Name);
Expand Down Expand Up @@ -571,7 +571,7 @@ public IObservable<bool> EnsureLocalBranchesAreMarkedAsPullRequests(ILocalReposi

public bool IsPullRequestFromRepository(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest)
{
return pullRequest.HeadRepositoryOwner == repository.CloneUrl.Owner;
return string.Equals(repository.CloneUrl?.Owner, pullRequest.HeadRepositoryOwner, StringComparison.OrdinalIgnoreCase);
}

public IObservable<Unit> SwitchToBranch(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest)
Expand Down
Expand Up @@ -7,6 +7,7 @@
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Windows.Threading;
using GitHub.Collections;
using GitHub.Extensions;
using GitHub.Extensions.Reactive;
Expand Down Expand Up @@ -209,6 +210,7 @@ public override Task Refresh()
this.WhenAnyValue(x => x.SelectedState),
this.WhenAnyValue(x => x.AuthorFilter.Selected),
(loading, count, _, __, ___) => Tuple.Create(loading, count))
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(x => UpdateState(x.Item1, x.Item2)));
dispose.Add(
Observable.FromEventPattern<ErrorEventArgs>(
Expand Down
Expand Up @@ -7,7 +7,9 @@
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Reactive.Threading.Tasks;
using System.Threading.Tasks;
using System.Windows.Input;
using GitHub.Extensions;
using GitHub.Models;
using GitHub.Services;
Expand Down Expand Up @@ -50,7 +52,7 @@ public sealed class PullRequestFilesViewModel : ViewModelBase, IPullRequestFiles
DiffFileWithWorkingDirectory = ReactiveCommand.CreateAsyncTask(
isBranchCheckedOut,
x => (Task)editorService.OpenDiff(pullRequestSession, ((IPullRequestFileNode)x).RelativePath));
OpenFileInWorkingDirectory = ReactiveCommand.CreateAsyncTask(
OpenFileInWorkingDirectory = new NonDeletedFileCommand(
isBranchCheckedOut,
x => (Task)editorService.OpenFile(pullRequestSession, ((IPullRequestFileNode)x).RelativePath, true));

Expand Down Expand Up @@ -198,5 +200,37 @@ async Task<IInlineCommentThreadModel> GetFirstCommentThread(IPullRequestFileNode

return threads.FirstOrDefault();
}

/// <summary>
/// Implements the <see cref="OpenFileInWorkingDirectory"/> command.
/// </summary>
/// <remarks>
/// We need to "Open File in Solution" when the parameter passed to the command parameter
/// represents a deleted file. ReactiveCommand doesn't allow us to change the CanExecute
/// state depending on the parameter, so we override
/// <see cref="ICommand.CanExecute(object)"/> to do this ourselves.
/// </remarks>
class NonDeletedFileCommand : ReactiveCommand<Unit>, ICommand
{
public NonDeletedFileCommand(
IObservable<bool> canExecute,
Func<object, Task> executeAsync)
: base(canExecute, x => executeAsync(x).ToObservable())
{
}

bool ICommand.CanExecute(object parameter)
{
if (parameter is IPullRequestFileNode node)
{
if (node.Status == PullRequestFileStatus.Removed)
{
return false;
}
}

return CanExecute(parameter);
}
}
}
}
Expand Up @@ -41,7 +41,7 @@ public class PullRequestReviewSummaryViewModel : IPullRequestReviewSummaryViewMo
{
var existing = new Dictionary<string, PullRequestReviewSummaryViewModel>();

foreach (var review in pullRequest.Reviews.OrderBy(x => x.Id))
foreach (var review in pullRequest.Reviews.OrderBy(x => x.SubmittedAt))
{
if (review.State == PullRequestReviewState.Pending && review.Author.Login != currentUser.Login)
continue;
Expand Down Expand Up @@ -90,6 +90,7 @@ static int ToPriority(PullRequestReviewState state)
{
case PullRequestReviewState.Approved:
case PullRequestReviewState.ChangesRequested:
case PullRequestReviewState.Dismissed:
return 1;
case PullRequestReviewState.Pending:
return 2;
Expand Down
35 changes: 25 additions & 10 deletions src/GitHub.InlineReviews/Margins/InlineCommentMarginProvider.cs
@@ -1,11 +1,13 @@
using System;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Tagging;
using Microsoft.VisualStudio.Text.Classification;
using GitHub.InlineReviews.Services;
using GitHub.Services;
using GitHub.VisualStudio;
using GitHub.InlineReviews.Services;

namespace GitHub.InlineReviews.Margins
{
Expand All @@ -17,28 +19,41 @@ namespace GitHub.InlineReviews.Margins
[TextViewRole(PredefinedTextViewRoles.Interactive)]
internal sealed class InlineCommentMarginProvider : IWpfTextViewMarginProvider
{
readonly IEditorFormatMapService editorFormatMapService;
readonly IViewTagAggregatorFactoryService tagAggregatorFactory;
readonly IInlineCommentPeekService peekService;
readonly Lazy<IEditorFormatMapService> editorFormatMapService;
readonly Lazy<IViewTagAggregatorFactoryService> tagAggregatorFactory;
readonly Lazy<IInlineCommentPeekService> peekService;
readonly Lazy<IPullRequestSessionManager> sessionManager;
readonly UIContext uiContext;

[ImportingConstructor]
public InlineCommentMarginProvider(
IGitHubServiceProvider serviceProvider,
IEditorFormatMapService editorFormatMapService,
IViewTagAggregatorFactoryService tagAggregatorFactory,
IInlineCommentPeekService peekService)
Lazy<IPullRequestSessionManager> sessionManager,
Lazy<IEditorFormatMapService> editorFormatMapService,
Lazy<IViewTagAggregatorFactoryService> tagAggregatorFactory,
Lazy<IInlineCommentPeekService> peekService)
{
this.sessionManager = sessionManager;
this.editorFormatMapService = editorFormatMapService;
this.tagAggregatorFactory = tagAggregatorFactory;
this.peekService = peekService;
sessionManager = new Lazy<IPullRequestSessionManager>(() => serviceProvider.GetService<IPullRequestSessionManager>());

uiContext = UIContext.FromUIContextGuid(new Guid(Guids.UIContext_Git));
}

public IWpfTextViewMargin CreateMargin(IWpfTextViewHost wpfTextViewHost, IWpfTextViewMargin parent)
{
if (!uiContext.IsActive)
{
// Only create margin when in the context of a Git repository
return null;
}

return new InlineCommentMargin(
wpfTextViewHost, peekService, editorFormatMapService, tagAggregatorFactory, sessionManager);
wpfTextViewHost,
peekService.Value,
editorFormatMapService.Value,
tagAggregatorFactory.Value,
sessionManager);
}
}
}
35 changes: 25 additions & 10 deletions src/GitHub.InlineReviews/Margins/PullRequestFileMarginProvider.cs
Expand Up @@ -3,6 +3,8 @@
using GitHub.Commands;
using GitHub.Services;
using GitHub.Settings;
using GitHub.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Utilities;
using Microsoft.VisualStudio.Text.Editor;

Expand All @@ -19,25 +21,28 @@ namespace GitHub.InlineReviews.Margins
[TextViewRole(PredefinedTextViewRoles.Editable)]
internal sealed class PullRequestFileMarginProvider : IWpfTextViewMarginProvider
{
readonly IPullRequestSessionManager sessionManager;
readonly IToggleInlineCommentMarginCommand enableInlineCommentsCommand;
readonly IGoToSolutionOrPullRequestFileCommand goToSolutionOrPullRequestFileCommand;
readonly IPackageSettings packageSettings;
readonly Lazy<IPullRequestSessionManager> sessionManager;
readonly Lazy<IToggleInlineCommentMarginCommand> enableInlineCommentsCommand;
readonly Lazy<IGoToSolutionOrPullRequestFileCommand> goToSolutionOrPullRequestFileCommand;
readonly Lazy<IPackageSettings> packageSettings;
readonly Lazy<IUsageTracker> usageTracker;
readonly UIContext uiContext;

[ImportingConstructor]
public PullRequestFileMarginProvider(
IToggleInlineCommentMarginCommand enableInlineCommentsCommand,
IGoToSolutionOrPullRequestFileCommand goToSolutionOrPullRequestFileCommand,
IPullRequestSessionManager sessionManager,
IPackageSettings packageSettings,
Lazy<IToggleInlineCommentMarginCommand> enableInlineCommentsCommand,
Lazy<IGoToSolutionOrPullRequestFileCommand> goToSolutionOrPullRequestFileCommand,
Lazy<IPullRequestSessionManager> sessionManager,
Lazy<IPackageSettings> packageSettings,
Lazy<IUsageTracker> usageTracker)
{
this.enableInlineCommentsCommand = enableInlineCommentsCommand;
this.goToSolutionOrPullRequestFileCommand = goToSolutionOrPullRequestFileCommand;
this.sessionManager = sessionManager;
this.packageSettings = packageSettings;
this.usageTracker = usageTracker;

uiContext = UIContext.FromUIContextGuid(new Guid(Guids.UIContext_Git));
}

/// <summary>
Expand All @@ -50,8 +55,14 @@ internal sealed class PullRequestFileMarginProvider : IWpfTextViewMarginProvider
/// </returns>
public IWpfTextViewMargin CreateMargin(IWpfTextViewHost wpfTextViewHost, IWpfTextViewMargin marginContainer)
{
if (!uiContext.IsActive)
{
// Only create margin when in the context of a Git repository
return null;
}

// Comments in the editor feature flag
if (!packageSettings.EditorComments)
if (!packageSettings.Value.EditorComments)
{
return null;
}
Expand All @@ -63,7 +74,11 @@ public IWpfTextViewMargin CreateMargin(IWpfTextViewHost wpfTextViewHost, IWpfTex
}

return new PullRequestFileMargin(
wpfTextViewHost.TextView, enableInlineCommentsCommand, goToSolutionOrPullRequestFileCommand, sessionManager, usageTracker);
wpfTextViewHost.TextView,
enableInlineCommentsCommand.Value,
goToSolutionOrPullRequestFileCommand.Value,
sessionManager.Value,
usageTracker);
}

bool IsDiffView(ITextView textView) => textView.Roles.Contains("DIFF");
Expand Down
Expand Up @@ -225,7 +225,7 @@ async Task<PullRequestSession> GetSessionInternal(string owner, string name, int
{
PullRequestSession session = null;
WeakReference<PullRequestSession> weakSession;
var key = Tuple.Create(owner, number);
var key = Tuple.Create(owner.ToLowerInvariant(), number);

if (sessions.TryGetValue(key, out weakSession))
{
Expand Down
6 changes: 3 additions & 3 deletions src/GitHub.TeamFoundation.14/Services/VSGitExt.cs
Expand Up @@ -12,6 +12,7 @@
using Microsoft.VisualStudio.Threading;
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;
using Task = System.Threading.Tasks.Task;
using static Microsoft.VisualStudio.VSConstants;

namespace GitHub.VisualStudio.Base
{
Expand Down Expand Up @@ -51,9 +52,8 @@ public VSGitExt(IAsyncServiceProvider asyncServiceProvider)
// Start with empty array until we have a chance to initialize.
ActiveRepositories = Array.Empty<ILocalRepositoryModel>();

// The IGitExt service isn't available when a TFS based solution is opened directly.
// It will become available when moving to a Git based solution (and cause a UIContext event to fire).
var context = factory.GetUIContext(new Guid(Guids.GitSccProviderId));
// Initialize when we enter the context of a Git repository
var context = factory.GetUIContext(UICONTEXT.RepositoryOpen_guid);
context.WhenActivated(() => JoinableTaskFactory.RunAsync(InitializeAsync).Task.Forget(log));
}

Expand Down
13 changes: 5 additions & 8 deletions src/GitHub.VisualStudio/GitContextPackage.cs
Expand Up @@ -2,31 +2,28 @@
using System.Threading;
using System.Runtime.InteropServices;
using GitHub.Exports;
using GitHub.Logging;
using GitHub.Services;
using Microsoft.VisualStudio.Shell;
using Serilog;
using Task = System.Threading.Tasks.Task;
using static Microsoft.VisualStudio.VSConstants;

namespace GitHub.VisualStudio
{
/// <summary>
/// This package creates a custom UIContext <see cref="Guids.UIContext_Git"/> that is activated when a
/// repository is active in <see cref="IVSGitExt"/>.
/// repository is active in <see cref="IVSGitExt"/> and the current process is Visual Studio (not Blend).
/// </summary>
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
[Guid(Guids.UIContext_Git)]
// this is the Git service GUID, so we load whenever it loads
[ProvideAutoLoad(Guids.GitSccProviderId, PackageAutoLoadFlags.BackgroundLoad)]
// Initialize when we enter the context of a Git repository
[ProvideAutoLoad(UICONTEXT.RepositoryOpen_string, PackageAutoLoadFlags.BackgroundLoad)]
public class GitContextPackage : AsyncPackage
{
static readonly ILogger log = LogManager.ForContext<GitContextPackage>();

protected async override Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
if (!ExportForVisualStudioProcessAttribute.IsVisualStudioProcess())
{
log.Warning("Don't activate 'UIContext_Git' for non-Visual Studio process");
// Don't activate 'UIContext_Git' for non-Visual Studio process
return;
}

Expand Down
30 changes: 16 additions & 14 deletions src/GitHub.VisualStudio/Resources/icons/mark_github.xaml
@@ -1,17 +1,19 @@
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Width="1024" Height="1024">
<Viewbox
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
Width="1024" Height="1024">

<Viewbox.Resources>
<ResourceDictionary>
<Color x:Key="GitHubContextMenuIconColor">#424242</Color>
<SolidColorBrush x:Key="GitHubContextMenuIconBrush" Color="{StaticResource GitHubContextMenuIconColor}" PresentationOptions:Freeze="true" />
</ResourceDictionary>
</Viewbox.Resources>

<Border BorderBrush="Transparent" BorderThickness="1">
<ghfvs:OcticonImage xmlns:ghfvs="https://github.com/github/VisualStudio"
Foreground="{DynamicResource GitHubContextMenuIconBrush}"
Icon="mark_github">
<ghfvs:OcticonImage.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ghfvs:SharedDictionaryManager Source="pack://application:,,,/GitHub.VisualStudio.UI;component/SharedDictionary.xaml" />
<ghfvs:SharedDictionaryManager Source="pack://application:,,,/GitHub.UI;component/SharedDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ghfvs:OcticonImage.Resources>
</ghfvs:OcticonImage>
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Width="16" Height="16">
<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Fill="{StaticResource GitHubContextMenuIconBrush}" Data="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
</Canvas>
</Border>
</Viewbox>
Expand Up @@ -61,13 +61,15 @@ void changesTree_MouseRightButtonDown(object sender, MouseButtonEventArgs e)

if (fileNode != null)
{
container.ContextMenu.DataContext = this.DataContext;

foreach (var menuItem in container.ContextMenu.Items.OfType<MenuItem>())
{
menuItem.CommandParameter = fileNode;
}

// HACK: MenuItem doesn't re-query ICommand.CanExecute when CommandParameter changes. Force
// this to happen by resetting its DataContext to null and then to the correct value.
container.ContextMenu.DataContext = null;
container.ContextMenu.DataContext = this.DataContext;
e.Handled = false;
}
}
Expand Down

0 comments on commit 14d5eca

Please sign in to comment.