public PullRequestFilesViewModel(
            IPullRequestService service,
            IPullRequestEditorService editorService)
        {
            Guard.ArgumentNotNull(service, nameof(service));
            Guard.ArgumentNotNull(editorService, nameof(editorService));

            this.service = service;

            DiffFile = ReactiveCommand.CreateFromTask <IPullRequestFileNode>(x =>
                                                                             editorService.OpenDiff(pullRequestSession, x.RelativePath, "HEAD"));
            ViewFile = ReactiveCommand.CreateFromTask <IPullRequestFileNode>(x =>
                                                                             editorService.OpenFile(pullRequestSession, x.RelativePath, false));
            DiffFileWithWorkingDirectory = ReactiveCommand.CreateFromTask <IPullRequestFileNode>(
                x => editorService.OpenDiff(pullRequestSession, x.RelativePath),
                isBranchCheckedOut);
            OpenFileInWorkingDirectory = ReactiveCommand.CreateFromTask <IPullRequestFileNode>(
                x => editorService.OpenFile(pullRequestSession, x.RelativePath, true),
                isBranchCheckedOut);

            OpenFirstComment = ReactiveCommand.CreateFromTask <IPullRequestFileNode>(async file =>
            {
                var thread = await GetFirstCommentThread(file);

                if (thread != null)
                {
                    await editorService.OpenDiff(pullRequestSession, file.RelativePath, thread);
                }
            });
        }
示例#2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PullRequestDetailViewModel"/> class.
        /// </summary>
        /// <param name="repositoryHost">The repository host.</param>
        /// <param name="teservice">The team explorer service.</param>
        /// <param name="pullRequestsService">The pull requests service.</param>
        /// <param name="avatarProvider">The avatar provider.</param>
        public PullRequestDetailViewModel(
            ILocalRepositoryModel repository,
            IModelService modelService,
            IPullRequestService pullRequestsService)
        {
            this.repository          = repository;
            this.modelService        = modelService;
            this.pullRequestsService = pullRequestsService;

            var canCheckout = this.WhenAnyValue(
                x => x.CheckoutMode,
                x => x.CheckoutDisabledMessage,
                (mode, disabled) => mode != CheckoutMode.UpToDate && mode != CheckoutMode.Push && disabled == null);

            Checkout = ReactiveCommand.CreateAsyncObservable(canCheckout, DoCheckout);

            OpenOnGitHub = ReactiveCommand.Create();

            ToggleChangedFilesView = ReactiveCommand.Create();
            ToggleChangedFilesView.Subscribe(_ =>
            {
                ChangedFilesViewType = ChangedFilesViewType == ChangedFilesViewType.TreeView ?
                                       ChangedFilesViewType.ListView : ChangedFilesViewType.TreeView;
            });

            ToggleOpenChangedFileAction = ReactiveCommand.Create();
            ToggleOpenChangedFileAction.Subscribe(_ =>
            {
                OpenChangedFileAction = OpenChangedFileAction == OpenChangedFileAction.Diff ?
                                        OpenChangedFileAction.Open : OpenChangedFileAction.Diff;
            });

            OpenFile = ReactiveCommand.Create();
            DiffFile = ReactiveCommand.Create();
        }
示例#3
0
        public PullRequestPageViewModel(
            IViewViewModelFactory factory,
            IPullRequestService service,
            IPullRequestSessionManager sessionManager,
            ITeamExplorerServices teServices,
            IVisualStudioBrowser visualStudioBrowser,
            IUsageTracker usageTracker)
        {
            Guard.ArgumentNotNull(factory, nameof(factory));
            Guard.ArgumentNotNull(service, nameof(service));
            Guard.ArgumentNotNull(sessionManager, nameof(sessionManager));
            Guard.ArgumentNotNull(visualStudioBrowser, nameof(visualStudioBrowser));
            Guard.ArgumentNotNull(teServices, nameof(teServices));

            this.factory             = factory;
            this.service             = service;
            this.sessionManager      = sessionManager;
            this.teServices          = teServices;
            this.visualStudioBrowser = visualStudioBrowser;
            this.usageTracker        = usageTracker;

            timeline.ItemsRemoved.Subscribe(TimelineItemRemoved);

            ShowCommit   = ReactiveCommand.CreateFromTask <string>(DoShowCommit);
            OpenOnGitHub = ReactiveCommand.Create(DoOpenOnGitHub);
        }
        static PullRequestReviewAuthoringViewModel CreateTarget(
            IPullRequestService pullRequestService    = null,
            IPullRequestEditorService editorService   = null,
            IPullRequestSessionManager sessionManager = null,
            IMessageDraftStore draftStore             = null,
            IPullRequestFilesViewModel files          = null,
            IScheduler timerScheduler = null,
            IAutoCompleteAdvisor autoCompleteAdvisor = null
            )
        {
            editorService       = editorService ?? Substitute.For <IPullRequestEditorService>();
            sessionManager      = sessionManager ?? CreateSessionManager();
            draftStore          = draftStore ?? Substitute.For <IMessageDraftStore>();
            files               = files ?? Substitute.For <IPullRequestFilesViewModel>();
            autoCompleteAdvisor = autoCompleteAdvisor ?? Substitute.For <IAutoCompleteAdvisor>();
            timerScheduler      = timerScheduler ?? DefaultScheduler.Instance;

            return(new PullRequestReviewAuthoringViewModel(
                       pullRequestService,
                       editorService,
                       sessionManager,
                       draftStore,
                       files,
                       autoCompleteAdvisor,
                       timerScheduler));
        }
示例#5
0
        public static async Task <IReadOnlyList <Contribution> > Get(
            IReadOnlyCollection <CommitterGroup> committerGroups, IPullRequestService pullRequestService)
        {
            Guard.AgainstNullArgument(nameof(committerGroups), committerGroups);
            Guard.AgainstNullArgument(nameof(pullRequestService), pullRequestService);

            return
                ((await Task.WhenAll(committerGroups.SelectMany(group => @group.RepositoryList.Select(id =>
            {
                log.InfoFormat("Getting pull requests for {@Repository}...", id);
                return pullRequestService.Get(id.Owner, id.Name).ContinueWith(task =>
                {
                    if (task.Exception != null)
                    {
                        log.ErrorException("Failed to get pull requests for {@Repository}.", task.Exception.InnerException, id);
                        return Enumerable.Empty <PullRequest>();
                    }

                    log.InfoFormat("Got pull requests for {@Repository}.", id);
                    return task.Result;
                });
            }))))
                 .SelectMany(_ => _)
                 .Select(pullRequest => new { pullRequest.Repository, Login = pullRequest.Creator, pullRequest.Created.LocalDateTime })
                 .Distinct()
                 .GroupBy(contribution => new
            {
                Group = committerGroups.First(group => @group.RepositoryList.Contains(contribution.Repository)).Name,
                contribution.Login
            })
                 .Select(g => new Contribution(g.Key.Group, g.Key.Login, g.Sum(contribution => Score(contribution.LocalDateTime))))
                 .ToList());
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="PullRequestDetailViewModel"/> class.
        /// </summary>
        /// <param name="repositoryHost">The repository host.</param>
        /// <param name="teservice">The team explorer service.</param>
        /// <param name="pullRequestsService">The pull requests service.</param>
        /// <param name="avatarProvider">The avatar provider.</param>
        public PullRequestDetailViewModel(
            ILocalRepositoryModel repository,
            IModelService modelService,
            IPullRequestService pullRequestsService,
            IPackageSettings settings)
        {
            this.repository = repository;
            this.modelService = modelService;
            this.pullRequestsService = pullRequestsService;

            Checkout = ReactiveCommand.CreateAsyncObservable(
                this.WhenAnyValue(x => x.CheckoutState)
                    .Cast<CheckoutCommandState>()
                    .Select(x => x != null && x.DisabledMessage == null), 
                DoCheckout);
            Checkout.ThrownExceptions.Subscribe(x => OperationError = x.Message);

            Pull = ReactiveCommand.CreateAsyncObservable(
                this.WhenAnyValue(x => x.UpdateState)
                    .Cast<UpdateCommandState>()
                    .Select(x => x != null && x.PullDisabledMessage == null),
                DoPull);
            Pull.ThrownExceptions.Subscribe(x => OperationError = x.Message);

            Push = ReactiveCommand.CreateAsyncObservable(
                this.WhenAnyValue(x => x.UpdateState)
                    .Cast<UpdateCommandState>()
                    .Select(x => x != null && x.PushDisabledMessage == null),
                DoPush);
            Push.ThrownExceptions.Subscribe(x => OperationError = x.Message);

            OpenOnGitHub = ReactiveCommand.Create();

            ChangedFilesViewType = (settings.UIState?.PullRequestDetailState?.ShowTree ?? true) ?
                ChangedFilesViewType.TreeView : ChangedFilesViewType.ListView;

            ToggleChangedFilesView = ReactiveCommand.Create();
            ToggleChangedFilesView.Subscribe(_ =>
            {
                ChangedFilesViewType = ChangedFilesViewType == ChangedFilesViewType.TreeView ?
                    ChangedFilesViewType.ListView : ChangedFilesViewType.TreeView;
                settings.UIState.PullRequestDetailState.ShowTree = ChangedFilesViewType == ChangedFilesViewType.TreeView;
                settings.Save();
            });

            OpenChangedFileAction = (settings.UIState?.PullRequestDetailState?.DiffOnOpen ?? true) ?
                OpenChangedFileAction.Diff : OpenChangedFileAction.Open;

            ToggleOpenChangedFileAction = ReactiveCommand.Create();
            ToggleOpenChangedFileAction.Subscribe(_ =>
            {
                OpenChangedFileAction = OpenChangedFileAction == OpenChangedFileAction.Diff ?
                    OpenChangedFileAction.Open : OpenChangedFileAction.Diff;
                settings.UIState.PullRequestDetailState.DiffOnOpen = OpenChangedFileAction == OpenChangedFileAction.Diff;
                settings.Save();
            });

            OpenFile = ReactiveCommand.Create();
            DiffFile = ReactiveCommand.Create();
        }
 public PullRequestCreationViewModel(
     IModelServiceFactory modelServiceFactory,
     IPullRequestService service,
     INotificationService notifications,
     IMessageDraftStore draftStore)
     : this(modelServiceFactory, service, notifications, draftStore, DefaultScheduler.Instance)
 {
 }
        public PullRequestDetailViewModel(
            IPullRequestService pullRequestsService,
            IPullRequestSessionManager sessionManager,
            IModelServiceFactory modelServiceFactory,
            IUsageTracker usageTracker,
            ITeamExplorerContext teamExplorerContext,
            IStatusBarNotificationService statusBarNotificationService)
        {
            Guard.ArgumentNotNull(pullRequestsService, nameof(pullRequestsService));
            Guard.ArgumentNotNull(sessionManager, nameof(sessionManager));
            Guard.ArgumentNotNull(modelServiceFactory, nameof(modelServiceFactory));
            Guard.ArgumentNotNull(usageTracker, nameof(usageTracker));
            Guard.ArgumentNotNull(teamExplorerContext, nameof(teamExplorerContext));
            Guard.ArgumentNotNull(statusBarNotificationService, nameof(statusBarNotificationService));

            this.pullRequestsService          = pullRequestsService;
            this.sessionManager               = sessionManager;
            this.modelServiceFactory          = modelServiceFactory;
            this.usageTracker                 = usageTracker;
            this.teamExplorerContext          = teamExplorerContext;
            this.statusBarNotificationService = statusBarNotificationService;

            Checkout = ReactiveCommand.CreateAsyncObservable(
                this.WhenAnyValue(x => x.CheckoutState)
                .Cast <CheckoutCommandState>()
                .Select(x => x != null && x.IsEnabled),
                DoCheckout);
            Checkout.IsExecuting.Subscribe(x => isInCheckout = x);
            SubscribeOperationError(Checkout);

            Pull = ReactiveCommand.CreateAsyncObservable(
                this.WhenAnyValue(x => x.UpdateState)
                .Cast <UpdateCommandState>()
                .Select(x => x != null && x.PullEnabled),
                DoPull);
            SubscribeOperationError(Pull);

            Push = ReactiveCommand.CreateAsyncObservable(
                this.WhenAnyValue(x => x.UpdateState)
                .Cast <UpdateCommandState>()
                .Select(x => x != null && x.PushEnabled),
                DoPush);
            SubscribeOperationError(Push);

            SyncSubmodules = ReactiveCommand.CreateAsyncTask(
                this.WhenAnyValue(x => x.UpdateState)
                .Cast <UpdateCommandState>()
                .Select(x => x != null && x.SyncSubmodulesEnabled),
                DoSyncSubmodules);
            SyncSubmodules.Subscribe(_ => Refresh().ToObservable());
            SubscribeOperationError(SyncSubmodules);

            OpenOnGitHub = ReactiveCommand.Create();
            DiffFile     = ReactiveCommand.Create();
            DiffFileWithWorkingDirectory = ReactiveCommand.Create(this.WhenAnyValue(x => x.IsCheckedOut));
            OpenFileInWorkingDirectory   = ReactiveCommand.Create(this.WhenAnyValue(x => x.IsCheckedOut));
            ViewFile = ReactiveCommand.Create();
        }
 public PullRequestReviewAuthoringViewModel(
     IPullRequestService pullRequestService,
     IPullRequestEditorService editorService,
     IPullRequestSessionManager sessionManager,
     IMessageDraftStore draftStore,
     IPullRequestFilesViewModel files)
     : this(pullRequestService, editorService, sessionManager, draftStore, files, DefaultScheduler.Instance)
 {
 }
示例#10
0
 public PostCommentService(
     IOptions <WebConfiguration> config,
     ICommentFactory commentFactory,
     IPullRequestService pullRequestService)
 {
     _config             = config?.Value ?? throw new ArgumentNullException(nameof(config));
     _commentFactory     = commentFactory ?? throw new ArgumentNullException(nameof(commentFactory));
     _pullRequestService = pullRequestService ?? throw new ArgumentNullException(nameof(pullRequestService));
 }
示例#11
0
 PullRequestDetailViewModel(
     IConnectionRepositoryHostMap connectionRepositoryHostMap,
     ITeamExplorerServiceHolder teservice,
     IPullRequestService pullRequestsService)
     : this(teservice.ActiveRepo,
            connectionRepositoryHostMap.CurrentRepositoryHost.ModelService,
            pullRequestsService)
 {
 }
示例#12
0
 public PullRequestCreationViewModel(
     IModelServiceFactory modelServiceFactory,
     IPullRequestService service,
     INotificationService notifications,
     IMessageDraftStore draftStore,
     IGitService gitService,
     IAutoCompleteAdvisor autoCompleteAdvisor)
     : this(modelServiceFactory, service, notifications, draftStore, gitService, autoCompleteAdvisor, DefaultScheduler.Instance)
 {
 }
 PullRequestDetailViewModel(
     IConnectionRepositoryHostMap connectionRepositoryHostMap,
     ITeamExplorerServiceHolder teservice,
     IPullRequestService pullRequestsService,
     IPackageSettings settings)
     : this(teservice.ActiveRepo,
           connectionRepositoryHostMap.CurrentRepositoryHost.ModelService,
           pullRequestsService,
           settings)
 {
 }
        static TeamExplorerContext CreateTeamExplorerContext(
            IVSGitExt gitExt,
            DTE dte = null,
            IPullRequestService pullRequestService = null)
        {
            dte = dte ?? Substitute.For <DTE>();
            pullRequestService = pullRequestService ?? Substitute.For <IPullRequestService>();
            var sp = Substitute.For <IGitHubServiceProvider>();

            sp.GetService <DTE>().Returns(dte);
            return(new TeamExplorerContext(sp, gitExt, pullRequestService));
        }
 PullRequestDetailViewModel(
     IGlobalConnection connection,
     IModelServiceFactory modelServiceFactory,
     ITeamExplorerServiceHolder teservice,
     IPullRequestService pullRequestsService,
     IPullRequestSessionManager sessionManager,
     IUsageTracker usageTracker)
     : this(teservice.ActiveRepo,
            modelServiceFactory.CreateBlocking(connection.Get()),
            pullRequestsService,
            sessionManager,
            usageTracker)
 {
 }
 TeamExplorerContext(
     IVSGitExt gitExt,
     [Import(typeof(SVsServiceProvider))] IServiceProvider sp,
     IPullRequestService pullRequestService) : this(
         gitExt,
         new AsyncLazy <DTE>(async() =>
 {
     await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
     return((DTE)sp.GetService(typeof(DTE)));
 }),
         pullRequestService,
         ThreadHelper.JoinableTaskContext)
 {
 }
示例#17
0
        public GitHubClient(IRestClientFactory factory,
                            IResponseProcessor processor)
        {
            Requires.ArgumentNotNull(factory, "factory");
            Requires.ArgumentNotNull(processor, "processor");

            _factory   = factory;
            _processor = processor;

            Authenticator  = new NullAuthenticator();
            _users         = new UserService(this);
            _issues        = new IssueService(this);
            _repositories  = new RepositoryService(this);
            _pullRequests  = new PullRequestService(this);
            _organizations = new OrganizationService(this);
        }
        public static async Task<IReadOnlyList<Contribution>> Get(
            IReadOnlyCollection<CommitterGroup> committerGroups, IPullRequestService pullRequestService)
        {
            Guard.AgainstNullArgument(nameof(committerGroups), committerGroups);
            Guard.AgainstNullArgument(nameof(pullRequestService), pullRequestService);

            return
                (await Task.WhenAll(committerGroups.SelectMany(group => @group.RepositoryList.Select(id =>
                {
                    log.InfoFormat("Getting pull requests for {@Repository}...", id);
                    return pullRequestService.Get(id.Owner, id.Name).ContinueWith(task =>
                    {
                        if (task.Exception != null)
                        {
                            log.ErrorException("Failed to get pull requests for {@Repository}.", task.Exception.InnerException, id);
                            return Enumerable.Empty<PullRequest>();
                        }

                        log.InfoFormat("Got pull requests for {@Repository}.", id);
                        return task.Result;
                    });
                }))))
                .SelectMany(_ => _)
                .Select(pullRequest => new { pullRequest.Repository, Login = pullRequest.Creator, pullRequest.Created.LocalDateTime })
                .Distinct()
                .GroupBy(contribution => new
                {
                    Group = committerGroups.First(group => @group.RepositoryList.Contains(contribution.Repository)).Name,
                    contribution.Login
                })
                .Select(g => new Contribution(g.Key.Group, g.Key.Login, g.Sum(contribution => Score(contribution.LocalDateTime))))
                .ToList();
        }
 PullRequestCreationViewModel(
      IConnectionRepositoryHostMap connectionRepositoryHostMap, ITeamExplorerServiceHolder teservice,
      IPullRequestService service, INotificationService notifications)
      : this(connectionRepositoryHostMap?.CurrentRepositoryHost, teservice?.ActiveRepo, service,
            notifications)
  {}
        public PullRequestCreationViewModel(IRepositoryHost repositoryHost, ILocalRepositoryModel activeRepo,
            IPullRequestService service, INotificationService notifications)
        {
            Extensions.Guard.ArgumentNotNull(repositoryHost, nameof(repositoryHost));
            Extensions.Guard.ArgumentNotNull(activeRepo, nameof(activeRepo));
            Extensions.Guard.ArgumentNotNull(service, nameof(service));
            Extensions.Guard.ArgumentNotNull(notifications, nameof(notifications));

            this.repositoryHost = repositoryHost;

            var obs = repositoryHost.ApiClient.GetRepository(activeRepo.Owner, activeRepo.Name)
                .Select(r => new RemoteRepositoryModel(r))
                .PublishLast();
            disposables.Add(obs.Connect());
            githubObs = obs;

            githubRepository = githubObs.ToProperty(this, x => x.GitHubRepository);

            this.WhenAnyValue(x => x.GitHubRepository)
                .WhereNotNull()
                .Subscribe(r =>
            {
                TargetBranch = r.IsFork ? r.Parent.DefaultBranch : r.DefaultBranch;
            });

            SourceBranch = activeRepo.CurrentBranch;
            service.GetPullRequestTemplate(activeRepo)
                .Subscribe(x => Description = x ?? String.Empty, () => Description = Description ?? String.Empty);

            this.WhenAnyValue(x => x.Branches)
                .WhereNotNull()
                .Where(_ => TargetBranch != null)
                .Subscribe(x =>
                {
                    if (!x.Any(t => t.Equals(TargetBranch)))
                        TargetBranch = GitHubRepository.IsFork ? GitHubRepository.Parent.DefaultBranch : GitHubRepository.DefaultBranch;
                });

            SetupValidators();

            var whenAnyValidationResultChanges = this.WhenAny(
                x => x.TitleValidator.ValidationResult,
                x => x.BranchValidator.ValidationResult,
                x => x.IsBusy,
                (x, y, z) => (x.Value?.IsValid ?? false) && (y.Value?.IsValid ?? false) && !z.Value);

            this.WhenAny(x => x.BranchValidator.ValidationResult, x => x.GetValue())
                .WhereNotNull()
                .Where(x => !x.IsValid && x.DisplayValidationError)
                .Subscribe(x => notifications.ShowError(BranchValidator.ValidationResult.Message));

            createPullRequest = ReactiveCommand.CreateAsyncObservable(whenAnyValidationResultChanges,
                _ => service
                    .CreatePullRequest(repositoryHost, activeRepo, TargetBranch.Repository, SourceBranch, TargetBranch, PRTitle, Description ?? String.Empty)
                    .Catch<IPullRequestModel, Exception>(ex =>
                    {
                        log.Error(ex);

                        //TODO:Will need a uniform solution to HTTP exception message handling
                        var apiException = ex as ApiValidationException;
                        var error = apiException?.ApiError?.Errors?.FirstOrDefault();
                        notifications.ShowError(error?.Message ?? ex.Message);
                        return Observable.Empty<IPullRequestModel>();
                    }))
            .OnExecuteCompleted(pr =>
            {
                notifications.ShowMessage(String.Format(CultureInfo.CurrentCulture, Resources.PRCreatedUpstream, SourceBranch.DisplayName, TargetBranch.Repository.Owner + "/" + TargetBranch.Repository.Name + "#" + pr.Number,
                    TargetBranch.Repository.CloneUrl.ToRepositoryUrl().Append("pull/" + pr.Number)));
            });

            isExecuting = CreatePullRequest.IsExecuting.ToProperty(this, x => x.IsExecuting);

            this.WhenAnyValue(x => x.Initialized, x => x.GitHubRepository, x => x.Description, x => x.IsExecuting)
                .Select(x => !(x.Item1 && x.Item2 != null && x.Item3 != null && !x.Item4))
                .Subscribe(x => IsBusy = x);
        }