示例#1
0
        public override void Initialize(ViewWithData data)
        {
            base.Initialize(data);

            if (modelService == null)
            {
                modelService = modelServiceFactory.CreateBlocking(connection);
            }

            IsBusy = true;
            modelService.GetRepositories(repositories);
            repositories.OriginalCompleted
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(
                _ => { }
                , ex =>
            {
                LoadingFailed = true;
                IsBusy        = false;
                log.Error(ex, "Error while loading repositories");
            },
                () => IsBusy = false
                );
            repositories.Subscribe();
        }
 PullRequestDetailViewModel(
     IGlobalConnection connection,
     IModelServiceFactory modelServiceFactory,
     ITeamExplorerServiceHolder teservice,
     IPullRequestService pullRequestsService,
     IPullRequestSessionManager sessionManager,
     IUsageTracker usageTracker)
     : this(teservice.ActiveRepo,
            modelServiceFactory.CreateBlocking(connection.Get()),
            pullRequestsService,
            sessionManager,
            usageTracker)
 {
 }
示例#3
0
        IObservable <ProgressState> OnPublishRepository()
        {
            var newRepository = GatherRepositoryInfo();
            var account       = SelectedAccount;
            var modelService  = modelServiceFactory.CreateBlocking(SelectedConnection);

            return(repositoryPublishService.PublishRepository(newRepository, account, modelService.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);
            }));
        }
示例#4
0
        public GistCreationViewModel(
            IConnection connection,
            IModelServiceFactory modelServiceFactory,
            ISelectedTextProvider selectedTextProvider,
            IGistPublishService gistPublishService,
            IUsageTracker usageTracker)
        {
            Guard.ArgumentNotNull(connection, nameof(connection));
            Guard.ArgumentNotNull(selectedTextProvider, nameof(selectedTextProvider));
            Guard.ArgumentNotNull(gistPublishService, nameof(gistPublishService));
            Guard.ArgumentNotNull(usageTracker, nameof(usageTracker));

            Title = Resources.CreateGistTitle;
            this.gistPublishService = gistPublishService;
            this.usageTracker       = usageTracker;

            FileName     = VisualStudio.Services.GetFileNameFromActiveDocument() ?? Resources.DefaultGistFileName;
            SelectedText = selectedTextProvider.GetSelectedText();

            var modelService = modelServiceFactory.CreateBlocking(connection);

            apiClient = modelService.ApiClient;

            // This class is only instantiated after we are logged into to a github account, so we should be safe to grab the first one here as the defaut.
            account = modelService.GetAccounts()
                      .FirstAsync()
                      .Select(a => a.First())
                      .ObserveOn(RxApp.MainThreadScheduler)
                      .ToProperty(this, vm => vm.Account);

            var canCreateGist = this.WhenAny(
                x => x.FileName,
                fileName => !String.IsNullOrEmpty(fileName.Value));

            CreateGist = ReactiveCommand.CreateAsyncObservable(canCreateGist, OnCreateGist);
        }
        public RepositoryCreationViewModel(
            IConnection connection,
            IModelServiceFactory modelServiceFactory,
            IOperatingSystem operatingSystem,
            IRepositoryCreationService repositoryCreationService,
            IUsageTracker usageTracker)
        {
            Guard.ArgumentNotNull(connection, nameof(connection));
            Guard.ArgumentNotNull(modelServiceFactory, nameof(modelServiceFactory));
            Guard.ArgumentNotNull(operatingSystem, nameof(operatingSystem));
            Guard.ArgumentNotNull(repositoryCreationService, nameof(repositoryCreationService));
            Guard.ArgumentNotNull(usageTracker, nameof(usageTracker));

            this.operatingSystem           = operatingSystem;
            this.repositoryCreationService = repositoryCreationService;
            this.usageTracker = usageTracker;

            Title = string.Format(CultureInfo.CurrentCulture, Resources.CreateTitle, connection.HostAddress.Title);
            SelectedGitIgnoreTemplate = GitIgnoreItem.None;
            SelectedLicense           = LicenseItem.None;

            modelService = modelServiceFactory.CreateBlocking(connection);

            accounts = modelService.GetAccounts()
                       .ObserveOn(RxApp.MainThreadScheduler)
                       .ToProperty(this, vm => vm.Accounts, initialValue: new ReadOnlyCollection <IAccount>(new IAccount[] {}));

            this.WhenAny(x => x.Accounts, x => x.Value)
            .Select(accts => accts?.FirstOrDefault())
            .WhereNotNull()
            .Subscribe(a => SelectedAccount = a);

            browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog());

            BaseRepositoryPathValidator = ReactivePropertyValidator.ForObservable(this.WhenAny(x => x.BaseRepositoryPath, x => x.Value))
                                          .IfNullOrEmpty(Resources.RepositoryCreationClonePathEmpty)
                                          .IfTrue(x => x.Length > 200, Resources.RepositoryCreationClonePathTooLong)
                                          .IfContainsInvalidPathChars(Resources.RepositoryCreationClonePathInvalidCharacters)
                                          .IfPathNotRooted(Resources.RepositoryCreationClonePathInvalid);

            var nonNullRepositoryName = this.WhenAny(
                x => x.RepositoryName,
                x => x.BaseRepositoryPath,
                (x, y) => x.Value)
                                        .WhereNotNull();

            RepositoryNameValidator = ReactivePropertyValidator.ForObservable(nonNullRepositoryName)
                                      .IfNullOrEmpty(Resources.RepositoryNameValidatorEmpty)
                                      .IfTrue(x => x.Length > 100, Resources.RepositoryNameValidatorTooLong)
                                      .IfTrue(IsAlreadyRepoAtPath, Resources.RepositoryNameValidatorAlreadyExists);

            SafeRepositoryNameWarningValidator = ReactivePropertyValidator.ForObservable(nonNullRepositoryName)
                                                 .Add(repoName =>
            {
                var parsedReference = GetSafeRepositoryName(repoName);
                return(parsedReference != repoName ? String.Format(CultureInfo.CurrentCulture, Resources.SafeRepositoryNameWarning, parsedReference) : null);
            });

            this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value)
            .Subscribe();

            CreateRepository = InitializeCreateRepositoryCommand();

            canKeepPrivate = CanKeepPrivateObservable.CombineLatest(CreateRepository.IsExecuting,
                                                                    (canKeep, publishing) => canKeep && !publishing)
                             .ToProperty(this, x => x.CanKeepPrivate);

            isCreating = CreateRepository.IsExecuting
                         .ToProperty(this, x => x.IsCreating);

            GitIgnoreTemplates = TrackingCollection.CreateListenerCollectionAndRun(
                modelService.GetGitIgnoreTemplates(),
                new[] { GitIgnoreItem.None },
                OrderedComparer <GitIgnoreItem> .OrderByDescending(item => GitIgnoreItem.IsRecommended(item.Name)).Compare,
                x =>
            {
                if (x.Name.Equals("VisualStudio", StringComparison.OrdinalIgnoreCase))
                {
                    SelectedGitIgnoreTemplate = x;
                }
            });

            Licenses = TrackingCollection.CreateListenerCollectionAndRun(
                modelService.GetLicenses(),
                new[] { LicenseItem.None },
                OrderedComparer <LicenseItem> .OrderByDescending(item => LicenseItem.IsRecommended(item.Name)).Compare);

            BaseRepositoryPath = repositoryCreationService.DefaultClonePath;
        }
        public PullRequestCreationViewModel(
            IConnection connection,
            IModelServiceFactory modelServiceFactory,
            ILocalRepositoryModel activeRepo,
            IPullRequestService service,
            INotificationService notifications)
        {
            Guard.ArgumentNotNull(connection, nameof(connection));
            Guard.ArgumentNotNull(modelServiceFactory, nameof(modelServiceFactory));
            Guard.ArgumentNotNull(activeRepo, nameof(activeRepo));
            Guard.ArgumentNotNull(service, nameof(service));
            Guard.ArgumentNotNull(notifications, nameof(notifications));

            activeLocalRepo = activeRepo;
            modelService    = modelServiceFactory.CreateBlocking(connection);

            var obs = modelService.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;

            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 uniqueCommits = this.WhenAnyValue(
                x => x.SourceBranch,
                x => x.TargetBranch)
                                .Where(x => x.Item1 != null && x.Item2 != null)
                                .Select(branches =>
            {
                var baseBranch    = branches.Item1.Name;
                var compareBranch = branches.Item2.Name;

                // We only need to get max two commits for what we're trying to achieve here.
                // If there's no commits we want to block creation of the PR, if there's one commits
                // we wan't to use its commit message as the PR title/body and finally if there's more
                // than one we'll use the branch name for the title.
                return(service.GetMessagesForUniqueCommits(activeRepo, baseBranch, compareBranch, maxCommits: 2)
                       .Catch <IReadOnlyList <CommitMessage>, Exception>(ex =>
                {
                    log.Warning(ex, "Could not load unique commits");
                    return Observable.Empty <IReadOnlyList <CommitMessage> >();
                }));
            })
                                .Switch()
                                .ObserveOn(RxApp.MainThreadScheduler)
                                .Replay(1)
                                .RefCount();

            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(modelService, activeRepo, TargetBranch.Repository, SourceBranch, TargetBranch, PRTitle, Description ?? String.Empty)
                                                                      .Catch <IPullRequestModel, Exception>(ex =>
            {
                log.Error(ex, "Error creating pull request");

                //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);

            Observable.CombineLatest(
                this.WhenAnyValue(x => x.SourceBranch),
                uniqueCommits,
                service.GetPullRequestTemplate(activeRepo).DefaultIfEmpty(string.Empty),
                (compare, commits, template) => new { compare, commits, template })
            .Subscribe(x =>
            {
                var prTitle       = string.Empty;
                var prDescription = string.Empty;

                if (x.commits.Count == 1)
                {
                    prTitle       = x.commits[0].Summary;
                    prDescription = x.commits[0].Details;
                }
                else
                {
                    prTitle = x.compare.Name.Humanize();
                }

                if (!string.IsNullOrWhiteSpace(x.template))
                {
                    if (!string.IsNullOrEmpty(prDescription))
                    {
                        prDescription += "\n\n";
                    }
                    prDescription += x.template;
                }

                PRTitle     = prTitle;
                Description = prDescription;
            });
        }