示例#1
0
        public IObservable <AuthenticationResult> LogInFromCache()
        {
            Func <Task <AuthenticationResult> > f = async() =>
            {
                try
                {
                    var user = await loginManager.LoginFromCache(Address, ApiClient.GitHubClient);

                    var accountCacheItem = new AccountCacheItem(user);

                    await usage.IncrementCounter(x => x.NumberOfLogins);

                    await ModelService.InsertUser(accountCacheItem);

                    if (user != null)
                    {
                        IsLoggedIn = true;
                        return(AuthenticationResult.Success);
                    }
                    else
                    {
                        return(AuthenticationResult.VerificationFailure);
                    }
                }
                catch (AuthorizationException)
                {
                    return(AuthenticationResult.CredentialFailure);
                }
            };

            return(f().ToObservable());
        }
示例#2
0
        void ShowWelcomeMessage()
        {
            teamExplorerServices.ShowMessage(
                Resources.TeamExplorerWelcomeMessage,
                new RelayCommand(o =>
            {
                var str = o.ToString();

                switch (str)
                {
                case "show-training":
                    visualStudioBrowser.OpenUrl(new Uri(TrainingUrl));
                    usageTracker.IncrementCounter(x => x.NumberOfWelcomeTrainingClicks).Forget();
                    break;

                case "show-docs":
                    visualStudioBrowser.OpenUrl(new Uri(GitHubUrls.Documentation));
                    usageTracker.IncrementCounter(x => x.NumberOfWelcomeDocsClicks).Forget();
                    break;

                case "dont-show-again":
                    teamExplorerServices.HideNotification(welcomeMessageGuid);
                    settings.HideTeamExplorerWelcomeMessage = true;
                    settings.Save();
                    break;
                }
            }),
                false,
                welcomeMessageGuid);
        }
        /// <inheritdoc/>
        public async Task <IPullRequestReviewModel> CreatePendingReview(
            ILocalRepositoryModel localRepository,
            IAccount user,
            string pullRequestId)
        {
            var address = HostAddress.Create(localRepository.CloneUrl.Host);
            var graphql = await graphqlFactory.CreateConnection(address);

            var review = new AddPullRequestReviewInput
            {
                PullRequestId = pullRequestId,
            };

            var addReview = new Mutation()
                            .AddPullRequestReview(review)
                            .Select(x => new PullRequestReviewModel
            {
                Id       = x.PullRequestReview.DatabaseId.Value,
                Body     = x.PullRequestReview.Body,
                CommitId = x.PullRequestReview.Commit.Oid,
                NodeId   = x.PullRequestReview.Id,
                State    = FromGraphQL(x.PullRequestReview.State),
                User     = user,
            });

            var result = await graphql.Run(addReview);

            await usageTracker.IncrementCounter(x => x.NumberOfPRReviewDiffViewInlineCommentStartReview);

            return(result);
        }
示例#4
0
        Tuple <ITextSnapshotLine, ITrackingPoint> GetLineAndTrackingPoint(
            ITextView textView,
            DiffSide side,
            int lineNumber)
        {
            var diffModel = (textView as IWpfTextView)?.TextViewModel as IDifferenceTextViewModel;
            var snapshot  = textView.TextSnapshot;

            if (diffModel?.ViewType == DifferenceViewType.InlineView)
            {
                snapshot = side == DiffSide.Left ?
                           diffModel.Viewer.DifferenceBuffer.LeftBuffer.CurrentSnapshot :
                           diffModel.Viewer.DifferenceBuffer.RightBuffer.CurrentSnapshot;
            }

            var line          = snapshot.GetLineFromLineNumber(lineNumber);
            var trackingPoint = snapshot.CreateTrackingPoint(line.Start.Position, PointTrackingMode.Positive);

            ExpandCollapsedRegions(textView, line.Extent);
            peekBroker.TriggerPeekSession(textView, trackingPoint, relationship);

            usageTracker.IncrementCounter(x => x.NumberOfPRReviewDiffViewInlineCommentOpen).Forget();

            return(Tuple.Create(line, trackingPoint));
        }
示例#5
0
        async Task <IPullRequestModel> PushAndCreatePR(IModelService modelService,
                                                       ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository,
                                                       IBranch sourceBranch, IBranch targetBranch,
                                                       string title, string body)
        {
            // PullRequestModel doesn't keep a reference to repo
            using (var repo = await Task.Run(() => gitService.GetRepository(sourceRepository.LocalPath)))
            {
                var remote = await gitClient.GetHttpRemote(repo, "origin");

                await gitClient.Push(repo, sourceBranch.Name, remote.Name);

                if (!repo.Branches[sourceBranch.Name].IsTracking)
                {
                    await gitClient.SetTrackingBranch(repo, sourceBranch.Name, remote.Name);
                }

                // delay things a bit to avoid a race between pushing a new branch and creating a PR on it
                if (!Splat.ModeDetector.Current.InUnitTestRunner().GetValueOrDefault())
                {
                    await Task.Delay(TimeSpan.FromSeconds(5));
                }

                var ret = await modelService.CreatePullRequest(sourceRepository, targetRepository, sourceBranch, targetBranch, title, body);

                await usageTracker.IncrementCounter(x => x.NumberOfUpstreamPullRequests);

                return(ret);
            }
        }
示例#6
0
        /// <inheritdoc/>
        public async Task CloneRepository(
            string cloneUrl,
            string repositoryName,
            string repositoryPath,
            object progress = null)
        {
            Guard.ArgumentNotEmptyString(cloneUrl, nameof(cloneUrl));
            Guard.ArgumentNotEmptyString(repositoryName, nameof(repositoryName));
            Guard.ArgumentNotEmptyString(repositoryPath, nameof(repositoryPath));

            string path = Path.Combine(repositoryPath, repositoryName);

            // Switch to a thread pool thread for IO then back to the main thread to call
            // vsGitServices.Clone() as this must be called on the main thread.
            await ThreadingHelper.SwitchToPoolThreadAsync();

            operatingSystem.Directory.CreateDirectory(path);
            await ThreadingHelper.SwitchToMainThreadAsync();

            try
            {
                await vsGitServices.Clone(cloneUrl, path, true, progress);

                await usageTracker.IncrementCounter(x => x.NumberOfClones);
            }
            catch (Exception ex)
            {
                log.Error(ex, "Could not clone {CloneUrl} to {Path}", cloneUrl, path);
                throw;
            }
        }
示例#7
0
        public IObservable <Repository> ForkRepository(IApiClient apiClient, IRepositoryModel sourceRepository, NewRepositoryFork repositoryFork, bool updateOrigin, bool addUpstream, bool trackMasterUpstream)
        {
            log.Verbose("ForkRepository Source:{SourceOwner}/{SourceName} To:{DestinationOwner}", sourceRepository.Owner, sourceRepository.Name, repositoryFork.Organization ?? "[Current User]");
            log.Verbose("ForkRepository updateOrigin:{UpdateOrigin} addUpstream:{AddUpstream} trackMasterUpstream:{TrackMasterUpstream}", updateOrigin, addUpstream, trackMasterUpstream);

            usageTracker.IncrementCounter(model => model.NumberOfReposForked).Forget();

            return(Observable.Defer(() => apiClient.ForkRepository(sourceRepository.Owner, sourceRepository.Name, repositoryFork)
                                    .ObserveOn(RxApp.MainThreadScheduler)
                                    .Select(remoteRepo => new { RemoteRepo = remoteRepo, ActiveRepo = updateOrigin ? vsGitServices.GetActiveRepo() : null }))
                   .SelectMany(async repo =>
            {
                if (repo.ActiveRepo != null)
                {
                    using (repo.ActiveRepo)
                    {
                        var originUri = repo.RemoteRepo != null ? new Uri(repo.RemoteRepo.CloneUrl) : null;
                        var upstreamUri = addUpstream ? sourceRepository.CloneUrl.ToUri() : null;

                        await SwitchRemotes(repo.ActiveRepo, originUri, upstreamUri, trackMasterUpstream);
                    }
                }

                return repo.RemoteRepo;
            }));
        }
示例#8
0
        public override async void Execute()
        {
            var connection = await connectionManager.GetConnection(ActiveRepo);

            if (connection?.IsLoggedIn == true)
            {
                usageTracker.IncrementCounter(model => model.NumberOfShowRepoForkDialogClicks).Forget();
                await dialogService.ShowForkDialog(ActiveRepo, connection);
            }
        }
示例#9
0
        private async Task RecordForkRepositoryUsage(bool updateOrigin, bool addUpstream, bool trackMasterUpstream)
        {
            await usageTracker.IncrementCounter(model => model.NumberOfReposForked);

            if (updateOrigin)
            {
                await usageTracker.IncrementCounter(model => model.NumberOfOriginsUpdatedWhenForkingRepo);
            }

            if (addUpstream)
            {
                await usageTracker.IncrementCounter(model => model.NumberOfUpstreamsAddedWhenForkingRepo);
            }

            if (trackMasterUpstream)
            {
                await usageTracker.IncrementCounter(model => model.NumberOfTrackMasterUpstreamWhenForkingRepo);
            }
        }
        IObservable <Unit> OnCreateRepository(object state)
        {
            var newRepository = GatherRepositoryInfo();

            return(repositoryCreationService.CreateRepository(
                       newRepository,
                       SelectedAccount,
                       BaseRepositoryPath,
                       modelService.ApiClient)
                   .Do(_ => usageTracker.IncrementCounter(x => x.NumberOfReposCreated).Forget()));
        }
        /// <inheritdoc/>
        public async Task <IConnection> LogIn(HostAddress address, string userName, string password)
        {
            var conns = await GetLoadedConnectionsInternal();

            if (conns.Any(x => x.HostAddress == address))
            {
                throw new InvalidOperationException($"A connection to {address} already exists.");
            }

            var client = CreateClient(address);
            var user   = await loginManager.Login(address, client, userName, password);

            var connection = new Connection(address, userName, user, null);

            conns.Add(connection);
            await SaveConnections();

            await usageTracker.IncrementCounter(x => x.NumberOfLogins);

            return(connection);
        }
示例#12
0
        /// <inheritdoc/>
        public async Task <IPullRequestReviewCommentModel> PostReviewComment(
            ILocalRepositoryModel localRepository,
            string remoteRepositoryOwner,
            IAccount user,
            int number,
            string body,
            string commitId,
            string path,
            int position)
        {
            var address   = HostAddress.Create(localRepository.CloneUrl.Host);
            var apiClient = await apiClientFactory.Create(address);

            var result = await apiClient.CreatePullRequestReviewComment(
                remoteRepositoryOwner,
                localRepository.Name,
                number,
                body,
                commitId,
                path,
                position);

            await usageTracker.IncrementCounter(x => x.NumberOfPRReviewDiffViewInlineCommentPost);

            return(new PullRequestReviewCommentModel
            {
                Body = result.Body,
                CommitId = result.CommitId,
                DiffHunk = result.DiffHunk,
                Id = result.Id,
                OriginalCommitId = result.OriginalCommitId,
                OriginalPosition = result.OriginalPosition,
                Path = result.Path,
                Position = result.Position,
                CreatedAt = result.CreatedAt,
                User = user,
            });
        }
示例#13
0
        private void DoOpenDetailsUrl()
        {
            Expression <Func <UsageModel.MeasuresModel, int> > expression;

            if (CheckType == PullRequestCheckType.StatusApi)
            {
                expression = x => x.NumberOfPRStatusesOpenInGitHub;
            }
            else
            {
                expression = x => x.NumberOfPRChecksOpenInGitHub;
            }

            usageTracker.IncrementCounter(expression).Forget();
        }
示例#14
0
            public void Execute(object parameter)
            {
                try
                {
                    object customIn  = null;
                    object customOut = null;
                    dte?.Commands.Raise(guid, id, ref customIn, ref customOut);
                }
                catch (Exception e)
                {
                    log.Error(e, "Couldn't raise {Guid}:{ID}", guid, id);
                }

                usageTracker.IncrementCounter(x => x.NumberOfShowCurrentPullRequest).Forget();
            }
示例#15
0
        /// <inheritdoc/>
        public async Task InitializeAsync(
            RemoteRepositoryModel repository,
            LocalRepositoryModel localRepository,
            ActorModel currentUser,
            PullRequestDetailModel model)
        {
            await base.InitializeAsync(repository, localRepository, model).ConfigureAwait(true);

            timeline.Clear();
            CommitCount      = 0;
            currentUserModel = currentUser;
            CurrentUser      = new ActorViewModel(currentUser);

            var commits = new List <CommitSummaryViewModel>();

            foreach (var i in model.Timeline)
            {
                if (!(i is CommitModel) && commits.Count > 0)
                {
                    timeline.Add(new CommitListViewModel(commits));
                    commits.Clear();
                }

                switch (i)
                {
                case CommitModel commit:
                    commits.Add(new CommitSummaryViewModel(commit));
                    ++CommitCount;
                    break;

                case CommentModel comment:
                    await AddComment(comment).ConfigureAwait(true);

                    break;
                }
            }

            if (commits.Count > 0)
            {
                timeline.Add(new CommitListViewModel(commits));
            }

            await AddPlaceholder().ConfigureAwait(true);

            await usageTracker.IncrementCounter(x => x.NumberOfPRConversationsOpened);
        }
示例#16
0
        IObservable <ProgressState> OnPublishRepository(object arg)
        {
            var newRepository = GatherRepositoryInfo();
            var account       = SelectedAccount;

            return(repositoryPublishService.PublishRepository(newRepository, account, SelectedHost.ApiClient)
                   .Do(_ => usageTracker.IncrementCounter(x => x.NumberOfReposPublished).Forget())
                   .Select(_ => ProgressState.Success)
                   .Catch <ProgressState, Exception>(ex =>
            {
                if (!ex.IsCriticalException())
                {
                    log.Error(ex, "Error Publishing Repository");
                    var error = new PublishRepositoryUserError(ex.Message);
                    notificationService.ShowError((error.ErrorMessage + Environment.NewLine + error.ErrorCauseOrResolution).TrimEnd());
                }
                return Observable.Return(ProgressState.Fail);
            }));
        }
示例#17
0
        /// <inheritdoc/>
        public async Task InitializeAsync(IServiceProvider paneServiceProvider)
        {
            await UpdateContent(teServiceHolder.ActiveRepo);

            teServiceHolder.Subscribe(this, x => UpdateContent(x).Forget());
            connectionManager.Connections.CollectionChanged += (_, __) => UpdateContent(LocalRepository).Forget();

            BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.pullRequestCommand, showPullRequests);
            BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.backCommand, navigator.NavigateBack);
            BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.forwardCommand, navigator.NavigateForward);
            BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.refreshCommand, refresh);
            BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.githubCommand, openInBrowser);

            paneServiceProvider.AddCommandHandler(Guids.guidGitHubToolbarCmdSet, PkgCmdIDList.helpCommand,
                                                  (_, __) =>
            {
                browser.OpenUrl(new Uri(GitHubUrls.Documentation));
                usageTracker.IncrementCounter(x => x.NumberOfGitHubPaneHelpClicks).Forget();
            });
        }
示例#18
0
        public async Task IncrementCounter(Expression <Func <UsageModel.MeasuresModel, int> > counter)
        {
            await Initialize();

            var property     = (MemberExpression)counter.Body;
            var propertyInfo = (PropertyInfo)property.Member;
            var counterName  = propertyInfo.Name;

            log.Verbose("Increment counter {Name}", counterName);

            var updateTask = UpdateUsageMetrics(propertyInfo);

            if (visualStudioUsageTracker != null)
            {
                // Not available on Visual Studio 2015
                await visualStudioUsageTracker.IncrementCounter(counter);
            }

            await updateTask;
        }
        void Load(PullRequestDetailModel pullRequest)
        {
            IsBusy = true;

            try
            {
                PullRequestTitle = pullRequest.Title;

                var checkSuiteRun = pullRequest
                                    .CheckSuites.SelectMany(checkSuite => checkSuite.CheckRuns
                                                            .Select(checkRun => new{ checkSuite, checkRun }))
                                    .First(arg => arg.checkRun.Id == CheckRunId);

                CheckSuiteName  = checkSuiteRun.checkSuite.ApplicationName;
                CheckRunName    = checkSuiteRun.checkRun.Name;
                CheckRunSummary = checkSuiteRun.checkRun.Summary;
                CheckRunText    = checkSuiteRun.checkRun.Text;

                var changedFiles = new HashSet <string>(session.PullRequest.ChangedFiles.Select(model => model.FileName));

                var annotationsLookup = checkSuiteRun.checkRun.Annotations
                                        .ToLookup(annotation => annotation.Path);

                AnnotationsDictionary = annotationsLookup
                                        .Select(models => models.Key)
                                        .OrderBy(s => s)
                                        .ToDictionary(
                    path => path,
                    path => annotationsLookup[path]
                    .Select(annotation => new PullRequestAnnotationItemViewModel(annotation, changedFiles.Contains(path), checkSuiteRun.checkSuite, session, pullRequestEditorService))
                    .Cast <IPullRequestAnnotationItemViewModel>()
                    .ToArray()
                    );

                usageTracker.IncrementCounter(x => x.NumberOfPullRequestOpenAnnotationsList).Forget();
            }
            finally
            {
                IsBusy = false;
            }
        }
示例#20
0
        /// <inheritdoc/>
        public async Task InitializeAsync(IServiceProvider paneServiceProvider)
        {
            await initializing.WaitAsync();

            if (initialized)
            {
                return;
            }

            try
            {
                await UpdateContent(teamExplorerContext.ActiveRepository);

                teamExplorerContext.WhenAnyValue(x => x.ActiveRepository)
                .Skip(1)
                .ObserveOn(RxApp.MainThreadScheduler)
                .Subscribe(x => UpdateContent(x).Forget());

                connectionManager.Connections.CollectionChanged += (_, __) => UpdateContent(LocalRepository).Forget();

                BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.pullRequestCommand, showPullRequests);
                BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.backCommand, navigator.NavigateBack);
                BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.forwardCommand, navigator.NavigateForward);
                BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.refreshCommand, refresh);
                BindNavigatorCommand(paneServiceProvider, PkgCmdIDList.githubCommand, openInBrowser);

                paneServiceProvider.AddCommandHandler(Guids.guidGitHubToolbarCmdSet, PkgCmdIDList.helpCommand,
                                                      (_, __) =>
                {
                    browser.OpenUrl(new Uri(GitHubUrls.Documentation));
                    usageTracker.IncrementCounter(x => x.NumberOfGitHubPaneHelpClicks).Forget();
                });
            }
            finally
            {
                initialized = true;
                initializing.Release();
            }
        }
示例#21
0
        IObservable <Gist> OnCreateGist(object unused)
        {
            var newGist = new NewGist
            {
                Description = Description,
                Public      = !IsPrivate
            };

            newGist.Files.Add(FileName, SelectedText);

            return(gistPublishService.PublishGist(apiClient, newGist)
                   .Do(_ => usageTracker.IncrementCounter(x => x.NumberOfGists).Forget())
                   .Catch <Gist, Exception>(ex =>
            {
                if (!ex.IsCriticalException())
                {
                    log.Error(ex, "Error Creating Gist");
                    var error = StandardUserErrors.GetUserFriendlyErrorMessage(ex, ErrorType.GistCreateFailed);
                    notificationService.ShowError(error);
                }
                return Observable.Return <Gist>(null);
            }));
        }
示例#22
0
        public GitHubPaneViewModel(
            IViewViewModelFactory viewModelFactory,
            ISimpleApiClientFactory apiClientFactory,
            IConnectionManager connectionManager,
            ITeamExplorerContext teamExplorerContext,
            IVisualStudioBrowser browser,
            IUsageTracker usageTracker,
            INavigationViewModel navigator,
            ILoggedOutViewModel loggedOut,
            INotAGitHubRepositoryViewModel notAGitHubRepository,
            INotAGitRepositoryViewModel notAGitRepository,
            INoRemoteOriginViewModel noRemoteOrigin,
            ILoginFailedViewModel loginFailed)
        {
            Guard.ArgumentNotNull(viewModelFactory, nameof(viewModelFactory));
            Guard.ArgumentNotNull(apiClientFactory, nameof(apiClientFactory));
            Guard.ArgumentNotNull(connectionManager, nameof(connectionManager));
            Guard.ArgumentNotNull(teamExplorerContext, nameof(teamExplorerContext));
            Guard.ArgumentNotNull(browser, nameof(browser));
            Guard.ArgumentNotNull(usageTracker, nameof(usageTracker));
            Guard.ArgumentNotNull(navigator, nameof(navigator));
            Guard.ArgumentNotNull(loggedOut, nameof(loggedOut));
            Guard.ArgumentNotNull(notAGitHubRepository, nameof(notAGitHubRepository));
            Guard.ArgumentNotNull(notAGitRepository, nameof(notAGitRepository));
            Guard.ArgumentNotNull(noRemoteOrigin, nameof(noRemoteOrigin));
            Guard.ArgumentNotNull(loginFailed, nameof(loginFailed));

            this.viewModelFactory     = viewModelFactory;
            this.apiClientFactory     = apiClientFactory;
            this.connectionManager    = connectionManager;
            this.teamExplorerContext  = teamExplorerContext;
            this.navigator            = navigator;
            this.loggedOut            = loggedOut;
            this.notAGitHubRepository = notAGitHubRepository;
            this.notAGitRepository    = notAGitRepository;
            this.noRemoteOrigin       = noRemoteOrigin;
            this.loginFailed          = loginFailed;

            var contentAndNavigatorContent = Observable.CombineLatest(
                this.WhenAnyValue(x => x.Content),
                navigator.WhenAnyValue(x => x.Content),
                (c, nc) => new { Content = c, NavigatorContent = nc });

            contentOverride = contentAndNavigatorContent
                              .SelectMany(x =>
            {
                if (x.Content == null)
                {
                    return(Observable.Return(ContentOverride.Spinner));
                }
                else if (x.Content == navigator && x.NavigatorContent != null)
                {
                    return(x.NavigatorContent.WhenAnyValue(
                               y => y.IsLoading,
                               y => y.Error,
                               (l, e) =>
                    {
                        if (l)
                        {
                            return ContentOverride.Spinner;
                        }
                        if (e != null)
                        {
                            return ContentOverride.Error;
                        }
                        else
                        {
                            return ContentOverride.None;
                        }
                    }));
                }
                else
                {
                    return(Observable.Return(ContentOverride.None));
                }
            })
                              .ToProperty(this, x => x.ContentOverride);

            // Returns navigator.Content if Content == navigator, otherwise null.
            var currentPage = contentAndNavigatorContent
                              .Select(x => x.Content == navigator ? x.NavigatorContent : null);

            title = currentPage
                    .SelectMany(x => x?.WhenAnyValue(y => y.Title) ?? Observable.Return <string>(null))
                    .Select(x => x ?? "GitHub")
                    .ToProperty(this, x => x.Title);

            isSearchEnabled = currentPage
                              .Select(x => x is ISearchablePageViewModel)
                              .ToProperty(this, x => x.IsSearchEnabled);

            refresh = ReactiveCommand.CreateFromTask(
                () => navigator.Content.Refresh(),
                currentPage.SelectMany(x => x?.WhenAnyValue(
                                           y => y.IsLoading,
                                           y => y.IsBusy,
                                           (loading, busy) => !loading && !busy)
                                       ?? Observable.Return(false)));
            refresh.ThrownExceptions.Subscribe();

            showPullRequests = ReactiveCommand.CreateFromTask(
                ShowPullRequests,
                this.WhenAny(x => x.Content, x => x.Value == navigator));

            openInBrowser = ReactiveCommand.Create(
                () =>
            {
                var url = ((IOpenInBrowser)navigator.Content).WebUrl;
                if (url != null)
                {
                    browser.OpenUrl(url);
                }
            },
                currentPage.Select(x => x is IOpenInBrowser));

            BrowseRepository = ReactiveCommand.Create(
                () =>
            {
                var url = LocalRepository.CloneUrl.ToRepositoryUrl();
                if (url != null)
                {
                    browser.OpenUrl(url);
                }
            },
                currentPage.Select(x => x is IOpenInBrowser));

            help = ReactiveCommand.Create(() => { });
            help.Subscribe(_ =>
            {
                browser.OpenUrl(new Uri(GitHubUrls.Documentation));
                usageTracker.IncrementCounter(x => x.NumberOfGitHubPaneHelpClicks).Forget();
            });

            navigator.WhenAnyObservable(x => x.Content.NavigationRequested)
            .Subscribe(x => NavigateTo(x).Forget());

            this.WhenAnyValue(x => x.SearchQuery)
            .Where(x => navigator.Content is ISearchablePageViewModel)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x => ((ISearchablePageViewModel)navigator.Content).SearchQuery = x);
        }
示例#23
0
        public override void Initialize(IServiceProvider serviceProvider)
        {
            Guard.ArgumentNotNull(serviceProvider, nameof(serviceProvider));

            serviceProvider.AddCommandHandler(Guids.guidGitHubToolbarCmdSet, PkgCmdIDList.pullRequestCommand,
                                              (s, e) => Load(new ViewWithData(UIControllerFlow.PullRequestList)).Forget());

            back = serviceProvider.AddCommandHandler(Guids.guidGitHubToolbarCmdSet, PkgCmdIDList.backCommand,
                                                     () => !disabled && (navController?.HasBack ?? false),
                                                     () =>
            {
                DisableButtons();
                navController.Back();
            },
                                                     true);

            forward = serviceProvider.AddCommandHandler(Guids.guidGitHubToolbarCmdSet, PkgCmdIDList.forwardCommand,
                                                        () => !disabled && (navController?.HasForward ?? false),
                                                        () =>
            {
                DisableButtons();
                navController.Forward();
            },
                                                        true);

            refresh = serviceProvider.AddCommandHandler(Guids.guidGitHubToolbarCmdSet, PkgCmdIDList.refreshCommand,
                                                        () => !disabled,
                                                        () =>
            {
                DisableButtons();
                Refresh();
            },
                                                        true);

            serviceProvider.AddCommandHandler(Guids.guidGitHubToolbarCmdSet, PkgCmdIDList.githubCommand,
                                              () => !disabled && (RepositoryOrigin == RepositoryOrigin.DotCom || RepositoryOrigin == RepositoryOrigin.Enterprise),
                                              () =>
            {
                switch (navController?.Current.CurrentFlow)
                {
                case UIControllerFlow.PullRequestDetail:
                    var prDetailViewModel = control.DataContext as IPullRequestDetailViewModel;
                    if (prDetailViewModel != null)
                    {
                        browser.OpenUrl(ActiveRepoUri.ToRepositoryUrl().Append("pull/" + prDetailViewModel.Model.Number));
                    }
                    else
                    {
                        goto default;
                    }
                    break;

                case UIControllerFlow.PullRequestList:
                case UIControllerFlow.PullRequestCreation:
                    browser.OpenUrl(ActiveRepoUri.ToRepositoryUrl().Append("pulls/"));
                    break;

                case UIControllerFlow.Home:
                default:
                    browser.OpenUrl(ActiveRepoUri.ToRepositoryUrl());
                    break;
                }
            },
                                              true);

            serviceProvider.AddCommandHandler(Guids.guidGitHubToolbarCmdSet, PkgCmdIDList.helpCommand,
                                              () => true,
                                              () =>
            {
                browser.OpenUrl(new Uri(GitHubUrls.Documentation));
                usageTracker.IncrementCounter(x => x.NumberOfGitHubPaneHelpClicks).Forget();
            },
                                              true);

            initialized = true;

            base.Initialize(serviceProvider);

            hosts.WhenAnyValue(x => x.IsLoggedInToAnyHost).Subscribe(_ => LoadDefault());
        }
示例#24
0
 public Task IncrementCounter(Expression <Func <UsageModel, int> > counter) => inner.IncrementCounter(counter);
示例#25
0
 public override void Execute()
 {
     openPullRequests.Execute();
     usageTracker.IncrementCounter(x => x.NumberOfTeamExplorerHomeOpenPullRequestList).Forget();
 }
 public void Execute(object parameter)
 {
     command.Execute(parameter);
     usageTracker.IncrementCounter(counter).Forget();
 }
示例#27
0
        /// <inheritdoc/>
        public async Task <ITextView> OpenFile(
            IPullRequestSession session,
            string relativePath,
            bool workingDirectory)
        {
            Guard.ArgumentNotNull(session, nameof(session));
            Guard.ArgumentNotEmptyString(relativePath, nameof(relativePath));

            try
            {
                var    fullPath = GetAbsolutePath(session.LocalRepository, relativePath);
                string fileName;
                string commitSha;

                if (workingDirectory)
                {
                    fileName  = fullPath;
                    commitSha = null;
                }
                else
                {
                    var file = await session.GetFile(relativePath);

                    fileName = await pullRequestService.ExtractToTempFile(
                        session.LocalRepository,
                        session.PullRequest,
                        file.RelativePath,
                        file.CommitSha,
                        pullRequestService.GetEncoding(session.LocalRepository, file.RelativePath));

                    commitSha = file.CommitSha;
                }

                IVsTextView  textView;
                IWpfTextView wpfTextView;
                using (workingDirectory ? null : OpenInProvisionalTab())
                {
                    var readOnly = !workingDirectory;
                    textView = OpenDocument(fileName, readOnly, out wpfTextView);

                    if (!workingDirectory)
                    {
                        AddBufferTag(wpfTextView.TextBuffer, session, fullPath, commitSha, null);
                        EnableNavigateToEditor(textView, session);
                    }
                }

                if (workingDirectory)
                {
                    await usageTracker.IncrementCounter(x => x.NumberOfPRDetailsOpenFileInSolution);
                }
                else
                {
                    await usageTracker.IncrementCounter(x => x.NumberOfPRDetailsViewFile);
                }

                return(wpfTextView);
            }
            catch (Exception e)
            {
                ShowErrorInStatusBar("Error opening file", e);
                return(null);
            }
        }
 private void DoOpenDetailsUrl(object obj)
 {
     usageTracker.IncrementCounter(x => x.NumberOfPRCheckStatusesOpenInGitHub).Forget();
 }
示例#29
0
        /// <summary>
        /// Loads the view model from octokit models.
        /// </summary>
        /// <param name="pullRequest">The pull request model.</param>
        public async Task Load(PullRequestDetailModel pullRequest)
        {
            try
            {
                var firstLoad = (Model == null);
                Model  = pullRequest;
                Author = new ActorViewModel(pullRequest.Author);
                Title  = Resources.PullRequestNavigationItemText + " #" + pullRequest.Number;

                IsBusy     = true;
                IsFromFork = !pullRequestsService.IsPullRequestFromRepository(LocalRepository, pullRequest);
                SourceBranchDisplayName = GetBranchDisplayName(IsFromFork, pullRequest.HeadRepositoryOwner, pullRequest.HeadRefName);
                TargetBranchDisplayName = GetBranchDisplayName(IsFromFork, pullRequest.BaseRepositoryOwner, pullRequest.BaseRefName);
                Body    = !string.IsNullOrWhiteSpace(pullRequest.Body) ? pullRequest.Body : Resources.NoDescriptionProvidedMarkdown;
                Reviews = PullRequestReviewSummaryViewModel.BuildByUser(Session.User, pullRequest).ToList();

                Checks = (IReadOnlyList <IPullRequestCheckViewModel>)PullRequestCheckViewModel.Build(viewViewModelFactory, pullRequest)?.ToList() ?? Array.Empty <IPullRequestCheckViewModel>();

                // Only show unresolved comments
                await Files.InitializeAsync(Session, c => !c.IsResolved);

                var localBranches = await pullRequestsService.GetLocalBranches(LocalRepository, pullRequest).ToList();

                var currentBranch = gitService.GetBranch(LocalRepository);
                IsCheckedOut = localBranches.Contains(currentBranch);

                if (IsCheckedOut)
                {
                    var divergence = await pullRequestsService.CalculateHistoryDivergence(LocalRepository, Model.Number);

                    var    pullEnabled = divergence.BehindBy > 0;
                    var    pushEnabled = divergence.AheadBy > 0 && !pullEnabled;
                    string pullToolTip;
                    string pushToolTip;

                    if (pullEnabled)
                    {
                        pullToolTip = string.Format(
                            CultureInfo.InvariantCulture,
                            Resources.PullRequestDetailsPullToolTip,
                            IsFromFork ? Resources.Fork : Resources.Remote,
                            SourceBranchDisplayName);
                    }
                    else
                    {
                        pullToolTip = Resources.NoCommitsToPull;
                    }

                    if (pushEnabled)
                    {
                        pushToolTip = string.Format(
                            CultureInfo.InvariantCulture,
                            Resources.PullRequestDetailsPushToolTip,
                            IsFromFork ? Resources.Fork : Resources.Remote,
                            SourceBranchDisplayName);
                    }
                    else if (divergence.AheadBy == 0)
                    {
                        pushToolTip = Resources.NoCommitsToPush;
                    }
                    else
                    {
                        pushToolTip = Resources.MustPullBeforePush;
                    }

                    var submodulesToSync = await pullRequestsService.CountSubmodulesToSync(LocalRepository);

                    var syncSubmodulesToolTip = string.Format(CultureInfo.InvariantCulture, Resources.SyncSubmodules, submodulesToSync);

                    UpdateState   = new UpdateCommandState(divergence, pullEnabled, pushEnabled, pullToolTip, pushToolTip, syncSubmodulesToolTip, submodulesToSync);
                    CheckoutState = null;
                }
                else
                {
                    var caption = localBranches.Count > 0 ?
                                  string.Format(
                        CultureInfo.InvariantCulture,
                        Resources.PullRequestDetailsCheckout,
                        localBranches.First().DisplayName) :
                                  string.Format(
                        CultureInfo.InvariantCulture,
                        Resources.PullRequestDetailsCheckoutTo,
                        await pullRequestsService.GetDefaultLocalBranchName(LocalRepository, Model.Number, Model.Title));
                    var clean = await pullRequestsService.IsWorkingDirectoryClean(LocalRepository);

                    string disabled = null;

                    if (pullRequest.HeadRepositoryOwner == null)
                    {
                        disabled = Resources.SourceRepositoryNoLongerAvailable;
                    }
                    else if (!clean)
                    {
                        disabled = Resources.WorkingDirectoryHasUncommittedCHanges;
                    }

                    CheckoutState = new CheckoutCommandState(caption, disabled);
                    UpdateState   = null;
                }

                sessionSubscription?.Dispose();
                sessionSubscription = Session.WhenAnyValue(x => x.HasPendingReview)
                                      .Skip(1)
                                      .Subscribe(x => Reviews = PullRequestReviewSummaryViewModel.BuildByUser(Session.User, Session.PullRequest).ToList());

                if (firstLoad)
                {
                    usageTracker.IncrementCounter(x => x.NumberOfPullRequestsOpened).Forget();
                }

                if (!isInCheckout)
                {
                    pullRequestsService.RemoveUnusedRemotes(LocalRepository).Subscribe(_ => { });
                }
            }
            finally
            {
                IsBusy = false;
            }
        }
        /// <inheritdoc/>
        public async Task OpenFile(
            IPullRequestSession session,
            string relativePath,
            bool workingDirectory)
        {
            Guard.ArgumentNotNull(session, nameof(session));
            Guard.ArgumentNotEmptyString(relativePath, nameof(relativePath));

            try
            {
                var    fullPath = Path.Combine(session.LocalRepository.LocalPath, relativePath);
                string fileName;
                string commitSha;

                if (workingDirectory)
                {
                    fileName  = fullPath;
                    commitSha = null;
                }
                else
                {
                    var file = await session.GetFile(relativePath);

                    fileName = await pullRequestService.ExtractToTempFile(
                        session.LocalRepository,
                        session.PullRequest,
                        file.RelativePath,
                        file.CommitSha,
                        pullRequestService.GetEncoding(session.LocalRepository, file.RelativePath));

                    commitSha = file.CommitSha;
                }

                using (workingDirectory ? null : OpenInProvisionalTab())
                {
                    var window = VisualStudio.Services.Dte.ItemOperations.OpenFile(fileName);
                    window.Document.ReadOnly = !workingDirectory;

                    var buffer = GetBufferAt(fileName);

                    if (!workingDirectory)
                    {
                        AddBufferTag(buffer, session, fullPath, commitSha, null);

                        var textView = FindActiveView();
                        var file     = await session.GetFile(relativePath);

                        EnableNavigateToEditor(textView, session, file);
                    }
                }

                if (workingDirectory)
                {
                    await usageTracker.IncrementCounter(x => x.NumberOfPRDetailsOpenFileInSolution);
                }
                else
                {
                    await usageTracker.IncrementCounter(x => x.NumberOfPRDetailsViewFile);
                }
            }
            catch (Exception e)
            {
                ShowErrorInStatusBar("Error opening file", e);
            }
        }