void UpdateRepo(ILocalRepositoryModel repo)
 {
     var changed = ActiveRepo != repo;
     ActiveRepo = repo;
     RepoChanged(changed);
     Invalidate();
 }
        /// <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 PullRequestListViewModel(
            IRepositoryHost repositoryHost,
            ILocalRepositoryModel repository,
            IPackageSettings settings)
        {
            this.repositoryHost = repositoryHost;
            this.repository = repository;
            this.settings = settings;

            Title = Resources.PullRequestsNavigationItemText;

            this.listSettings = settings.UIState
                .GetOrCreateRepositoryState(repository.CloneUrl)
                .PullRequests;

            openPullRequestCommand = ReactiveCommand.Create();
            openPullRequestCommand.Subscribe(_ =>
            {
                VisualStudio.Services.DefaultExportProvider.GetExportedValue<IVisualStudioBrowser>().OpenUrl(repositoryHost.Address.WebUri);
            });

            States = new List<PullRequestState> {
                new PullRequestState { IsOpen = true, Name = "Open" },
                new PullRequestState { IsOpen = false, Name = "Closed" },
                new PullRequestState { Name = "All" }
            };

            trackingAuthors = new TrackingCollection<IAccount>(Observable.Empty<IAccount>(),
                OrderedComparer<IAccount>.OrderByDescending(x => x.Login).Compare);
            trackingAssignees = new TrackingCollection<IAccount>(Observable.Empty<IAccount>(),
                OrderedComparer<IAccount>.OrderByDescending(x => x.Login).Compare);
            trackingAuthors.Subscribe();
            trackingAssignees.Subscribe();

            Authors = trackingAuthors.CreateListenerCollection(EmptyUser, this.WhenAnyValue(x => x.SelectedAuthor));
            Assignees = trackingAssignees.CreateListenerCollection(EmptyUser, this.WhenAnyValue(x => x.SelectedAssignee));

            PullRequests = new TrackingCollection<IPullRequestModel>();
            pullRequests.Comparer = OrderedComparer<IPullRequestModel>.OrderByDescending(x => x.UpdatedAt).Compare;
            pullRequests.NewerComparer = OrderedComparer<IPullRequestModel>.OrderByDescending(x => x.UpdatedAt).Compare;

            this.WhenAny(x => x.SelectedState, x => x.Value)
                .Where(x => PullRequests != null)
                .Subscribe(s => UpdateFilter(s, SelectedAssignee, SelectedAuthor));

            this.WhenAny(x => x.SelectedAssignee, x => x.Value)
                .Where(x => PullRequests != null && x != EmptyUser && IsLoaded)
                .Subscribe(a => UpdateFilter(SelectedState, a, SelectedAuthor));

            this.WhenAny(x => x.SelectedAuthor, x => x.Value)
                .Where(x => PullRequests != null && x != EmptyUser && IsLoaded)
                .Subscribe(a => UpdateFilter(SelectedState, SelectedAssignee, a));

            SelectedState = States.FirstOrDefault(x => x.Name == listSettings.SelectedState) ?? States[0];
        }
        void BuildAccounts(IReadOnlyList <IAccount> accessibleAccounts, ILocalRepositoryModel currentRepository, IList <IRemoteRepositoryModel> forks, List <IRemoteRepositoryModel> parents)
        {
            log.Verbose("BuildAccounts: {AccessibleAccounts} accessibleAccounts, {Forks} forks, {Parents} parents", accessibleAccounts.Count, forks.Count, parents.Count);

            var existingForksAndParents = forks.Union(parents).ToDictionary(model => model.Owner);

            var readOnlyList = accessibleAccounts
                               .Where(account => account.Login != currentRepository.Owner)
                               .Select(account => new { Account = account, Fork = existingForksAndParents.ContainsKey(account.Login) ? existingForksAndParents[account.Login] : null })
                               .ToArray();

            Accounts      = readOnlyList.Where(arg => arg.Fork == null).Select(arg => arg.Account).ToList();
            ExistingForks = readOnlyList.Where(arg => arg.Fork != null).Select(arg => arg.Fork).ToList();
        }
Ejemplo n.º 5
0
 public IObservable <Tuple <string, int> > GetPullRequestForCurrentBranch(ILocalRepositoryModel repository)
 {
     return(Observable.Defer(async() =>
     {
         var repo = gitService.GetRepository(repository.LocalPath);
         var configKey = string.Format(
             CultureInfo.InvariantCulture,
             "branch.{0}.{1}",
             repo.Head.FriendlyName,
             SettingGHfVSPullRequest);
         var value = await gitClient.GetConfig <string>(repo, configKey);
         return Observable.Return(ParseGHfVSConfigKeyValue(value));
     }));
 }
Ejemplo n.º 6
0
 public IObservable <TreeChanges> GetTreeChanges(ILocalRepositoryModel repository, PullRequestDetailModel pullRequest)
 {
     return(Observable.Defer(async() =>
     {
         // TreeChanges doesn't keep a reference to Repository
         using (var repo = gitService.GetRepository(repository.LocalPath))
         {
             var remote = await gitClient.GetHttpRemote(repo, "origin");
             await gitClient.Fetch(repo, remote.Name);
             var changes = await gitClient.Compare(repo, pullRequest.BaseRefSha, pullRequest.HeadRefSha, detectRenames: true);
             return Observable.Return(changes);
         }
     }));
 }
Ejemplo n.º 7
0
        /// <inheritdoc/>
        public async Task InitializeAsync(ILocalRepositoryModel repository, IConnection connection)
        {
            try
            {
                LocalRepository = repository;
                SelectedState   = States.FirstOrDefault();
                AuthorFilter    = new UserFilterViewModel(LoadAuthors);
                IsLoading       = true;

                var parent = await repositoryService.FindParent(
                    HostAddress.Create(repository.CloneUrl),
                    repository.Owner,
                    repository.Name);

                if (parent == null)
                {
                    RemoteRepository = repository;
                }
                else
                {
                    // TODO: Handle forks with different names.
                    RemoteRepository = new RepositoryModel(
                        repository.Name,
                        UriString.ToUriString(repository.CloneUrl.ToRepositoryUrl(parent.Value.owner)));

                    Forks = new IRepositoryModel[]
                    {
                        RemoteRepository,
                        repository,
                    };
                }

                this.WhenAnyValue(x => x.SelectedState, x => x.RemoteRepository)
                .Skip(1)
                .Subscribe(_ => Refresh().Forget());

                Observable.Merge(
                    this.WhenAnyValue(x => x.SearchQuery).Skip(1).SelectUnit(),
                    AuthorFilter.WhenAnyValue(x => x.Selected).Skip(1).SelectUnit())
                .Subscribe(_ => FilterChanged());

                await Refresh();
            }
            catch (Exception ex)
            {
                Error     = ex;
                IsLoading = false;
                log.Error(ex, "Error initializing IssueListViewModelBase");
            }
        }
Ejemplo n.º 8
0
 public IObservable <bool> IsWorkingDirectoryClean(ILocalRepositoryModel repository)
 {
     // The `using` appears to resolve this issue:
     // https://github.com/github/VisualStudio/issues/1306
     using (var repo = gitService.GetRepository(repository.LocalPath))
     {
         var statusOptions = new StatusOptions {
             ExcludeSubmodules = true
         };
         var status  = repo.RetrieveStatus(statusOptions);
         var isClean = !IsCheckoutBlockingDirty(status);
         return(Observable.Return(isClean));
     }
 }
        async Task RepoChanged(ILocalRepositoryModel repository)
        {
            try
            {
                await ThreadingHelper.SwitchToMainThreadAsync();
                await EnsureLoggedIn(repository);

                if (repository != this.repository)
                {
                    this.repository = repository;
                    CurrentSession  = null;
                    sessions.Clear();
                }

                var modelService = hosts.LookupHost(HostAddress.Create(repository.CloneUrl))?.ModelService;
                var session      = CurrentSession;

                if (modelService != null)
                {
                    var pr = await service.GetPullRequestForCurrentBranch(repository).FirstOrDefaultAsync();

                    if (pr?.Item1 != (CurrentSession?.PullRequest.Base.RepositoryCloneUrl.Owner) &&
                        pr?.Item2 != (CurrentSession?.PullRequest.Number))
                    {
                        var pullRequest = await GetPullRequestForTip(modelService, repository);

                        if (pullRequest != null)
                        {
                            var newSession = await GetSessionInternal(pullRequest);;
                            if (newSession != null)
                            {
                                newSession.IsCheckedOut = true;
                            }
                            session = newSession;
                        }
                    }
                }
                else
                {
                    session = null;
                }

                CurrentSession = session;
            }
            catch
            {
                // TODO: Log
            }
        }
Ejemplo n.º 10
0
        public async Task <string> GetGraphQLPullRequestId(
            ILocalRepositoryModel localRepository,
            string repositoryOwner,
            int number)
        {
            var address = HostAddress.Create(localRepository.CloneUrl.Host);
            var graphql = await graphqlFactory.CreateConnection(address);

            var query = new Query()
                        .Repository(repositoryOwner, localRepository.Name)
                        .PullRequest(number)
                        .Select(x => x.Id);

            return((await graphql.Run(query)).Value);
        }
        async Task RepoChanged(ILocalRepositoryModel localRepositoryModel)
        {
            repository     = localRepositoryModel;
            CurrentSession = null;
            sessions.Clear();

            if (localRepositoryModel != null)
            {
                await StatusChanged();
            }
            else
            {
                initialized.TrySetResult(null);
            }
        }
Ejemplo n.º 12
0
        /// <inheritdoc/>
        public async Task <PullRequestDetailModel> CreatePendingReview(
            ILocalRepositoryModel localRepository,
            string pullRequestId)
        {
            var address = HostAddress.Create(localRepository.CloneUrl.Host);
            var graphql = await graphqlFactory.CreateConnection(address);

            var(_, owner, number) = await CreatePendingReviewCore(localRepository, pullRequestId);

            var detail = await ReadPullRequestDetail(address, owner, localRepository.Name, number);

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

            return(detail);
        }
        void RefreshCurrentSession(ILocalRepositoryModel repository, IPullRequestSession session)
        {
            var cloneUrl = repository?.CloneUrl;

            if (cloneUrl != null)
            {
                // Only show PR status bar if repo has remote
                var viewModel = CreatePullRequestStatusViewModel(session);
                ShowStatus(viewModel);
            }
            else
            {
                ShowStatus(null);
            }
        }
Ejemplo n.º 14
0
        public IObservable <BranchTrackingDetails> CalculateHistoryDivergence(ILocalRepositoryModel repository, int pullRequestNumber)
        {
            return(Observable.Defer(async() =>
            {
                var repo = gitService.GetRepository(repository.LocalPath);

                if (repo.Head.Remote != null)
                {
                    var remote = await gitClient.GetHttpRemote(repo, repo.Head.Remote.Name);
                    await gitClient.Fetch(repo, remote.Name);
                }

                return Observable.Return(repo.Head.TrackingDetails);
            }));
        }
Ejemplo n.º 15
0
 public IObservable <IPullRequestModel> GetPullRequest(ILocalRepositoryModel repo, int number)
 {
     return(Observable.Defer(() =>
     {
         return hostCache.GetAndRefreshObject(PRPrefix + '|' + number, () =>
                                              Observable.CombineLatest(
                                                  apiClient.GetPullRequest(repo.CloneUrl.Owner, repo.CloneUrl.RepositoryName, number),
                                                  apiClient.GetPullRequestFiles(repo.CloneUrl.Owner, repo.CloneUrl.RepositoryName, number).ToList(),
                                                  (pr, files) => new { PullRequest = pr, Files = files })
                                              .Select(x => PullRequestCacheItem.Create(x.PullRequest, (IReadOnlyList <PullRequestFile>)x.Files)),
                                              TimeSpan.Zero,
                                              TimeSpan.FromDays(7))
         .Select(Create);
     }));
 }
Ejemplo n.º 16
0
        public Encoding GetEncoding(ILocalRepositoryModel repository, string relativePath)
        {
            var fullPath = Path.Combine(repository.LocalPath, relativePath);

            if (File.Exists(fullPath))
            {
                var encoding = Encoding.UTF8;
                if (HasPreamble(fullPath, encoding))
                {
                    return(encoding);
                }
            }

            return(Encoding.Default);
        }
Ejemplo n.º 17
0
        /// <inheritdoc/>
        public async Task <IPullRequestReviewCommentModel> PostStandaloneReviewCommentReply(
            ILocalRepositoryModel localRepository,
            IAccount user,
            string pullRequestNodeId,
            string body,
            string inReplyToNodeId)
        {
            var review = await CreatePendingReview(localRepository, user, pullRequestNodeId);

            var comment = await PostPendingReviewCommentReply(localRepository, user, review.NodeId, body, inReplyToNodeId);

            await SubmitPendingReview(localRepository, user, review.NodeId, null, PullRequestReviewEvent.Comment);

            comment.IsPending = false;
            return(comment);
        }
        /// <inheritdoc/>
        public async Task DeleteComment(
            ILocalRepositoryModel localRepository,
            string remoteRepositoryOwner,
            IAccount user,
            int number)
        {
            var address   = HostAddress.Create(localRepository.CloneUrl.Host);
            var apiClient = await apiClientFactory.Create(address);

            await apiClient.DeletePullRequestReviewComment(
                remoteRepositoryOwner,
                localRepository.Name,
                number);

            await usageTracker.IncrementCounter(x => x.NumberOfPRReviewDiffViewInlineCommentDelete);
        }
Ejemplo n.º 19
0
 public IObservable <IReadOnlyList <CommitMessage> > GetMessagesForUniqueCommits(
     ILocalRepositoryModel repository,
     string baseBranch,
     string compareBranch,
     int maxCommits)
 {
     return(Observable.Defer(async() =>
     {
         // CommitMessage doesn't keep a reference to Repository
         using (var repo = gitService.GetRepository(repository.LocalPath))
         {
             var messages = await gitClient.GetMessagesForUniqueCommits(repo, baseBranch, compareBranch, maxCommits);
             return Observable.Return(messages);
         }
     }));
 }
Ejemplo n.º 20
0
        void HandleClonedRepo(ILocalRepositoryModel newrepo)
        {
            Guard.ArgumentNotNull(newrepo, nameof(newrepo));

            var msg = string.Format(CultureInfo.CurrentCulture, Constants.Notification_RepoCloned, newrepo.Name, newrepo.CloneUrl);

            if (newrepo.HasCommits() && newrepo.MightContainSolution())
            {
                msg += " " + string.Format(CultureInfo.CurrentCulture, Constants.Notification_OpenProject, newrepo.LocalPath);
            }
            else
            {
                msg += " " + string.Format(CultureInfo.CurrentCulture, Constants.Notification_CreateNewProject, newrepo.LocalPath);
            }
            ShowNotification(newrepo, msg);
        }
Ejemplo n.º 21
0
        public IObservable <IPullRequestModel> CreatePullRequest(IModelService modelService,
                                                                 ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository,
                                                                 IBranch sourceBranch, IBranch targetBranch,
                                                                 string title, string body
                                                                 )
        {
            Extensions.Guard.ArgumentNotNull(modelService, nameof(modelService));
            Extensions.Guard.ArgumentNotNull(sourceRepository, nameof(sourceRepository));
            Extensions.Guard.ArgumentNotNull(targetRepository, nameof(targetRepository));
            Extensions.Guard.ArgumentNotNull(sourceBranch, nameof(sourceBranch));
            Extensions.Guard.ArgumentNotNull(targetBranch, nameof(targetBranch));
            Extensions.Guard.ArgumentNotNull(title, nameof(title));
            Extensions.Guard.ArgumentNotNull(body, nameof(body));

            return(PushAndCreatePR(modelService, sourceRepository, targetRepository, sourceBranch, targetBranch, title, body).ToObservable());
        }
Ejemplo n.º 22
0
        public IObservable<IPullRequestModel> CreatePullRequest(IRepositoryHost host,
            ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository,
            IBranch sourceBranch, IBranch targetBranch,
            string title, string body
        )
        {
            Extensions.Guard.ArgumentNotNull(host, nameof(host));
            Extensions.Guard.ArgumentNotNull(sourceRepository, nameof(sourceRepository));
            Extensions.Guard.ArgumentNotNull(targetRepository, nameof(targetRepository));
            Extensions.Guard.ArgumentNotNull(sourceBranch, nameof(sourceBranch));
            Extensions.Guard.ArgumentNotNull(targetBranch, nameof(targetBranch));
            Extensions.Guard.ArgumentNotNull(title, nameof(title));
            Extensions.Guard.ArgumentNotNull(body, nameof(body));

            return PushAndCreatePR(host, sourceRepository, targetRepository, sourceBranch, targetBranch, title, body).ToObservable();
        }
        /// <inheritdoc/>
        public async Task <IPullRequestReviewCommentModel> PostPendingReviewComment(
            ILocalRepositoryModel localRepository,
            IAccount user,
            string pendingReviewId,
            string body,
            string commitId,
            string path,
            int position)
        {
            var address = HostAddress.Create(localRepository.CloneUrl.Host);
            var graphql = await graphqlFactory.CreateConnection(address);

            var comment = new AddPullRequestReviewCommentInput
            {
                Body                = body,
                CommitOID           = commitId,
                Path                = path,
                Position            = position,
                PullRequestReviewId = pendingReviewId,
            };

            var addComment = new Mutation()
                             .AddPullRequestReviewComment(comment)
                             .Select(x => new PullRequestReviewCommentModel
            {
                Id                  = x.Comment.DatabaseId.Value,
                NodeId              = x.Comment.Id,
                Body                = x.Comment.Body,
                CommitId            = x.Comment.Commit.Oid,
                Path                = x.Comment.Path,
                Position            = x.Comment.Position,
                CreatedAt           = x.Comment.CreatedAt.Value,
                DiffHunk            = x.Comment.DiffHunk,
                OriginalPosition    = x.Comment.OriginalPosition,
                OriginalCommitId    = x.Comment.OriginalCommit.Oid,
                PullRequestReviewId = x.Comment.PullRequestReview.DatabaseId.Value,
                User                = user,
                IsPending           = true,
            });

            var result = await graphql.Run(addComment);

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

            return(result);
        }
        public async Task InitializeAsync(
            ILocalRepositoryModel localRepository,
            IConnection connection,
            string owner,
            string repo,
            int pullRequestNumber)
        {
            if (repo != localRepository.Name)
            {
                throw new NotSupportedException();
            }

            IsLoading = true;

            try
            {
                LocalRepository       = localRepository;
                RemoteRepositoryOwner = owner;
                session = await sessionManager.GetSession(owner, repo, pullRequestNumber).ConfigureAwait(true);
                await Load(session.PullRequest).ConfigureAwait(true);

                if (LocalRepository?.CloneUrl != null)
                {
                    var key = GetDraftKey();

                    if (string.IsNullOrEmpty(Body))
                    {
                        var draft = await draftStore.GetDraft <PullRequestReviewDraft>(key, string.Empty)
                                    .ConfigureAwait(true);

                        Body = draft?.Body;
                    }

                    this.WhenAnyValue(x => x.Body)
                    .Throttle(TimeSpan.FromSeconds(1), timerScheduler)
                    .Select(x => new PullRequestReviewDraft {
                        Body = x
                    })
                    .Subscribe(x => draftStore.UpdateDraft(key, string.Empty, x));
                }
            }
            finally
            {
                IsLoading = false;
            }
        }
Ejemplo n.º 25
0
        async Task UpdateContent(ILocalRepositoryModel repository)
        {
            LocalRepository = repository;
            Connection      = null;

            Content = null;

            if (repository == null)
            {
                Content = notAGitRepository;
                return;
            }
            else if (string.IsNullOrWhiteSpace(repository.CloneUrl))
            {
                Content = notAGitHubRepository;
                return;
            }

            var repositoryUrl = repository.CloneUrl.ToRepositoryUrl();
            var isDotCom      = HostAddress.IsGitHubDotComUri(repositoryUrl);
            var client        = await apiClientFactory.Create(repository.CloneUrl);

            var isEnterprise = isDotCom ? false : client.IsEnterprise();

            if ((isDotCom || isEnterprise) && await IsValidRepository(client))
            {
                var hostAddress = HostAddress.Create(repository.CloneUrl);

                Connection = await connectionManager.GetConnection(hostAddress);

                if (Connection != null)
                {
                    navigator.Clear();
                    Content = navigator;
                    await ShowDefaultPage();
                }
                else
                {
                    Content = loggedOut;
                }
            }
            else
            {
                Content = notAGitHubRepository;
            }
        }
Ejemplo n.º 26
0
        public IObservable <string> GetDefaultLocalBranchName(ILocalRepositoryModel repository, int pullRequestNumber, string pullRequestTitle)
        {
            return(Observable.Defer(() =>
            {
                var initial = "pr/" + pullRequestNumber + "-" + GetSafeBranchName(pullRequestTitle);
                var current = initial;
                var repo = gitService.GetRepository(repository.LocalPath);
                var index = 2;

                while (repo.Branches[current] != null)
                {
                    current = initial + '-' + index++;
                }

                return Observable.Return(current);
            }));
        }
    public void CreatePullRequestAllArgsMandatory()
    {
        var serviceProvider = Substitutes.ServiceProvider;
        var gitService      = serviceProvider.GetGitService();
        var service         = new PullRequestService(
            Substitute.For <IGitClient>(),
            serviceProvider.GetGitService(),
            Substitute.For <IVSGitExt>(),
            Substitute.For <IGraphQLClientFactory>(),
            serviceProvider.GetOperatingSystem(),
            Substitute.For <IUsageTracker>());

        IModelService         ms         = null;
        ILocalRepositoryModel sourceRepo = null;
        ILocalRepositoryModel targetRepo = null;
        string  title  = null;
        string  body   = null;
        IBranch source = null;
        IBranch target = null;

        Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(ms, sourceRepo, targetRepo, source, target, title, body));

        ms = Substitute.For <IModelService>();
        Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(ms, sourceRepo, targetRepo, source, target, title, body));

        sourceRepo = new LocalRepositoryModel("name", new GitHub.Primitives.UriString("http://github.com/github/stuff"), "c:\\path", gitService);
        Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(ms, sourceRepo, targetRepo, source, target, title, body));

        targetRepo = new LocalRepositoryModel("name", new GitHub.Primitives.UriString("http://github.com/github/stuff"), "c:\\path", gitService);
        Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(ms, sourceRepo, targetRepo, source, target, title, body));

        title = "a title";
        Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(ms, sourceRepo, targetRepo, source, target, title, body));

        body = "a body";
        Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(ms, sourceRepo, targetRepo, source, target, title, body));

        source = new BranchModel("source", sourceRepo);
        Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(ms, sourceRepo, targetRepo, source, target, title, body));

        target = new BranchModel("target", targetRepo);
        var pr = service.CreatePullRequest(ms, sourceRepo, targetRepo, source, target, title, body);

        Assert.NotNull(pr);
    }
Ejemplo n.º 28
0
        void ShowNotification(ILocalRepositoryModel newrepo, string msg)
        {
            Guard.ArgumentNotNull(newrepo, nameof(newrepo));

            var teServices = ServiceProvider.TryGetService <ITeamExplorerServices>();

            teServices.ClearNotifications();
            teServices.ShowMessage(
                msg,
                new RelayCommand(o =>
            {
                var str = o.ToString();

                /* the prefix is the action to perform:
                 * u: launch browser with url
                 * c: launch create new project dialog
                 * o: launch open existing project dialog
                 */
                var prefix = str.Substring(0, 2);
                if (prefix == "u:")
                {
                    OpenInBrowser(ServiceProvider.TryGetService <IVisualStudioBrowser>(), new Uri(str.Substring(2)));
                }
                else if (prefix == "o:")
                {
                    if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().OpenSolutionViaDlg(str.Substring(2), 1)))
                    {
                        ServiceProvider.TryGetService <ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null);
                    }
                }
                else if (prefix == "c:")
                {
                    var vsGitServices = ServiceProvider.TryGetService <IVSGitServices>();
                    vsGitServices.SetDefaultProjectPath(newrepo.LocalPath);
                    if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().CreateNewProjectViaDlg(null, null, 0)))
                    {
                        ServiceProvider.TryGetService <ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null);
                    }
                }
            })
                );
#if DEBUG
            VsOutputLogger.WriteLine(String.Format(CultureInfo.InvariantCulture, "{0} Notification", DateTime.Now));
#endif
        }
Ejemplo n.º 29
0
        public PullRequestSession(
            IPullRequestSessionService service,
            IAccount user,
            IPullRequestModel pullRequest,
            ILocalRepositoryModel repository,
            bool isCheckedOut)
        {
            Guard.ArgumentNotNull(service, nameof(service));
            Guard.ArgumentNotNull(user, nameof(user));
            Guard.ArgumentNotNull(pullRequest, nameof(pullRequest));
            Guard.ArgumentNotNull(repository, nameof(repository));

            this.service      = service;
            this.isCheckedOut = isCheckedOut;
            User        = user;
            PullRequest = pullRequest;
            Repository  = repository;
        }
        async Task InitializeAsync(
            PullRequestUserReviewsViewModel target,
            ILocalRepositoryModel localRepository = null,
            IConnection connection = null,
            int pullRequestNumber  = 5,
            string login           = AuthorLogin)
        {
            localRepository = localRepository ?? CreateRepository();
            connection      = connection ?? Substitute.For <IConnection>();

            await target.InitializeAsync(
                localRepository,
                connection,
                localRepository.Owner,
                localRepository.Name,
                pullRequestNumber,
                login);
        }
Ejemplo n.º 31
0
 IEnumerable <string> GetLocalBranchesInternal(
     ILocalRepositoryModel localRepository,
     IRepository repository,
     IPullRequestModel pullRequest)
 {
     if (!IsPullRequestFromFork(localRepository, pullRequest))
     {
         return(new[] { pullRequest.Head.Ref });
     }
     else
     {
         var pr = pullRequest.Number.ToString(CultureInfo.InvariantCulture);
         return(repository.Config
                .Select(x => new { Branch = BranchCapture.Match(x.Key).Groups["branch"].Value, Value = x.Value })
                .Where(x => !string.IsNullOrWhiteSpace(x.Branch) && x.Value == pr)
                .Select(x => x.Branch));
     }
 }
Ejemplo n.º 32
0
        public IObservable <string> GetPullRequestTemplate(ILocalRepositoryModel repository)
        {
            Extensions.Guard.ArgumentNotNull(repository, nameof(repository));

            return(Observable.Defer(() =>
            {
                var paths = TemplatePaths.Select(x => Path.Combine(repository.LocalPath, x));

                foreach (var path in paths)
                {
                    if (os.File.Exists(path))
                    {
                        try { return Observable.Return(os.File.ReadAllText(path, Encoding.UTF8)); } catch { }
                    }
                }
                return Observable.Empty <string>();
            }));
        }
Ejemplo n.º 33
0
        /// <inheritdoc/>
        public async Task <PullRequestDetailModel> DeleteComment(
            ILocalRepositoryModel localRepository,
            string remoteRepositoryOwner,
            int pullRequestId,
            int commentDatabaseId)
        {
            var address   = HostAddress.Create(localRepository.CloneUrl.Host);
            var apiClient = await apiClientFactory.Create(address);

            await apiClient.DeletePullRequestReviewComment(
                remoteRepositoryOwner,
                localRepository.Name,
                commentDatabaseId);

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

            return(await ReadPullRequestDetail(address, remoteRepositoryOwner, localRepository.Name, pullRequestId));
        }
Ejemplo n.º 34
0
        public IObservable<string> GetPullRequestTemplate(ILocalRepositoryModel repository)
        {
            Extensions.Guard.ArgumentNotNull(repository, nameof(repository));

            return Observable.Defer(() =>
            {
                var paths = TemplatePaths.Select(x => Path.Combine(repository.LocalPath, x));

                foreach (var path in paths)
                {
                    if (os.File.Exists(path))
                    {
                        try { return Observable.Return(os.File.ReadAllText(path, Encoding.UTF8)); } catch { }
                    }
                }
                return Observable.Empty<string>();
            });
        }
        public async Task InitializeAsync(ILocalRepositoryModel sourceRepository, IAccount destinationAccount, IConnection connection)
        {
            var modelService = await modelServiceFactory.CreateAsync(connection);

            apiClient = modelService.ApiClient;

            DestinationAccount = destinationAccount;

            SourceRepository      = sourceRepository;
            DestinationRepository = new RemoteRepositoryModel(
                0,
                sourceRepository.Name,
                CreateForkUri(sourceRepository.CloneUrl, destinationAccount.Login),
                false,
                true,
                destinationAccount,
                null);
        }
Ejemplo n.º 36
0
        async Task<IPullRequestModel> PushAndCreatePR(IRepositoryHost host,
            ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository,
            IBranch sourceBranch, IBranch targetBranch,
            string title, string body)
        {
            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 host.ModelService.CreatePullRequest(sourceRepository, targetRepository, sourceBranch, targetBranch, title, body);
            await usageTracker.IncrementUpstreamPullRequestCount();
            return ret;
        }
Ejemplo n.º 37
0
 void HandleCreatedRepo(ILocalRepositoryModel newrepo)
 {
     var msg = string.Format(CultureInfo.CurrentUICulture, Constants.Notification_RepoCreated, newrepo.Name, newrepo.CloneUrl);
     msg += " " + string.Format(CultureInfo.CurrentUICulture, Constants.Notification_CreateNewProject, newrepo.LocalPath);
     ShowNotification(newrepo, msg);
 }
Ejemplo n.º 38
0
        async void UpdateRepositoryList(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                // if we're cloning or creating, only one repo will be added to the list
                // so we can handle just one new entry separately
                if (isCloning || isCreating)
                {
                    var newrepo = e.NewItems.Cast<ILocalRepositoryModel>().First();

                    SelectedRepository = newrepo;
                    if (isCreating)
                        HandleCreatedRepo(newrepo);
                    else
                        HandleClonedRepo(newrepo);

                    isCreating = isCloning = false;

                    try
                    {
                        // TODO: Cache the icon state.
                        var repo = await ApiFactory.Create(newrepo.CloneUrl).GetRepository();
                        newrepo.SetIcon(repo.Private, repo.Fork);
                    }
                    catch
                    {
                        // GetRepository() may throw if the user doesn't have permissions to access the repo
                        // (because the repo no longer exists, or because the user has logged in on a different
                        // profile, or their permissions have changed remotely)
                        // TODO: Log
                    }
                }
                // looks like it's just a refresh with new stuff on the list, update the icons
                else
                {
                    e.NewItems
                        .Cast<ILocalRepositoryModel>()
                        .ForEach(async r =>
                    {
                        if (Equals(Holder.ActiveRepo, r))
                            SelectedRepository = r;

                        try
                        {
                            // TODO: Cache the icon state.
                            var repo = await ApiFactory.Create(r.CloneUrl).GetRepository();
                            r.SetIcon(repo.Private, repo.Fork);
                        }
                        catch
                        {
                            // GetRepository() may throw if the user doesn't have permissions to access the repo
                            // (because the repo no longer exists, or because the user has logged in on a different
                            // profile, or their permissions have changed remotely)
                            // TODO: Log
                        }
                    });
                }
            }
        }
Ejemplo n.º 39
0
 public IObservable<Unit> Push(ILocalRepositoryModel repository)
 {
     return Observable.Defer(() =>
     {
         var repo = gitService.GetRepository(repository.LocalPath);
         return gitClient.Push(repo, repo.Head.TrackedBranch.UpstreamBranchCanonicalName, repo.Head.Remote.Name).ToObservable();
     });
 }
Ejemplo n.º 40
0
 public IObservable<Unit> Pull(ILocalRepositoryModel repository)
 {
     return Observable.Defer(() =>
     {
         var repo = gitService.GetRepository(repository.LocalPath);
         return gitClient.Pull(repo).ToObservable();
     });
 }
Ejemplo n.º 41
0
 public IObservable<bool> IsWorkingDirectoryClean(ILocalRepositoryModel repository)
 {
     var repo = gitService.GetRepository(repository.LocalPath);
     return Observable.Return(!repo.RetrieveStatus().IsDirty);
 }
Ejemplo n.º 42
0
 public IObservable<IBranch> GetLocalBranches(ILocalRepositoryModel repository, IPullRequestModel pullRequest)
 {
     return Observable.Defer(() =>
     {
         var repo = gitService.GetRepository(repository.LocalPath);
         var result = GetLocalBranchesInternal(repository, repo, pullRequest).Select(x => new BranchModel(x, repository));
         return result.ToObservable();
     });
 }
Ejemplo n.º 43
0
 public IObservable<IPullRequestModel> GetPullRequest(ILocalRepositoryModel repo, int number)
 {
     return Observable.Defer(() =>
     {
         return hostCache.GetAndRefreshObject(PRPrefix + '|' + number, () =>
                 Observable.CombineLatest(
                     apiClient.GetPullRequest(repo.CloneUrl.Owner, repo.CloneUrl.RepositoryName, number),
                     apiClient.GetPullRequestFiles(repo.CloneUrl.Owner, repo.CloneUrl.RepositoryName, number).ToList(),
                     (pr, files) => new { PullRequest = pr, Files = files })
                     .Select(x => PullRequestCacheItem.Create(x.PullRequest, (IReadOnlyList<PullRequestFile>)x.Files)),
                 TimeSpan.Zero,
                 TimeSpan.FromDays(7))
             .Select(Create);
     });
 }
Ejemplo n.º 44
0
        public IObservable<IPullRequestModel> CreatePullRequest(ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository,
            IBranch sourceBranch, IBranch targetBranch,
            string title, string body)
        {
            var keyobs = GetUserFromCache()
                .Select(user => string.Format(CultureInfo.InvariantCulture, "{0}|{1}:{2}", CacheIndex.PRPrefix, targetRepository.Owner, targetRepository.Name));

            return Observable.Defer(() => keyobs
                .SelectMany(key =>
                    hostCache.PutAndUpdateIndex(key, () =>
                        apiClient.CreatePullRequest(
                                new NewPullRequest(title,
                                                   string.Format(CultureInfo.InvariantCulture, "{0}:{1}", sourceRepository.Owner, sourceBranch.Name),
                                                   targetBranch.Name)
                                                   { Body = body },
                                targetRepository.Owner,
                                targetRepository.Name)
                            .Select(PullRequestCacheItem.Create)
                        ,
                        TimeSpan.FromMinutes(30))
                )
                .Select(Create)
            );
        }
Ejemplo n.º 45
0
 IEnumerable<string> GetLocalBranchesInternal(
     ILocalRepositoryModel localRepository,
     IRepository repository,
     IPullRequestModel pullRequest)
 {
     if (!IsPullRequestFromFork(localRepository, pullRequest))
     {
         return new[] { pullRequest.Head.Ref };
     }
     else
     {
         var pr = pullRequest.Number.ToString(CultureInfo.InvariantCulture);
         return repository.Config
             .Select(x => new { Branch = BranchCapture.Match(x.Key).Groups["branch"].Value, Value = x.Value })
             .Where(x => !string.IsNullOrWhiteSpace(x.Branch) && x.Value == pr)
             .Select(x => x.Branch);
     }
 }
Ejemplo n.º 46
0
        void ShowNotification(ILocalRepositoryModel newrepo, string msg)
        {
            var teServices = ServiceProvider.GetExportedValue<ITeamExplorerServices>();
            
            teServices.ClearNotifications();
            teServices.ShowMessage(
                msg,
                new RelayCommand(o =>
                {
                    var str = o.ToString();
                    /* the prefix is the action to perform:
                     * u: launch browser with url
                     * c: launch create new project dialog
                     * o: launch open existing project dialog 
                    */
                    var prefix = str.Substring(0, 2);
                    if (prefix == "u:")
                        OpenInBrowser(ServiceProvider.GetExportedValue<IVisualStudioBrowser>(), new Uri(str.Substring(2)));
                    else if (prefix == "o:")
                    {
                        if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().OpenSolutionViaDlg(str.Substring(2), 1)))
                            ServiceProvider.TryGetService<ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null);
                    }
                    else if (prefix == "c:")
                    {
                        var vsGitServices = ServiceProvider.GetExportedValue<IVSGitServices>();
                        vsGitServices.SetDefaultProjectPath(newrepo.LocalPath);
                        if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().CreateNewProjectViaDlg(null, null, 0)))
                            ServiceProvider.TryGetService<ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null);
                    }
                })
            );
#if DEBUG
            VsOutputLogger.WriteLine(String.Format(CultureInfo.InvariantCulture, "{0} Notification", DateTime.Now));
#endif
        }
Ejemplo n.º 47
0
        /// <summary>
        /// Gets a collection of Pull Requests. If you want to refresh existing data, pass a collection in
        /// </summary>
        /// <param name="repo"></param>
        /// <param name="collection"></param>
        /// <returns></returns>
        public ITrackingCollection<IPullRequestModel> GetPullRequests(ILocalRepositoryModel repo,
            ITrackingCollection<IPullRequestModel> collection)
        {
            // Since the api to list pull requests returns all the data for each pr, cache each pr in its own entry
            // and also cache an index that contains all the keys for each pr. This way we can fetch prs in bulk
            // but also individually without duplicating information. We store things in a custom observable collection
            // that checks whether an item is being updated (coming from the live stream after being retrieved from cache)
            // and replaces it instead of appending, so items get refreshed in-place as they come in.

            var keyobs = GetUserFromCache()
                .Select(user => string.Format(CultureInfo.InvariantCulture, "{0}|{1}:{2}", CacheIndex.PRPrefix, user.Login, repo.Name));

            var source = Observable.Defer(() => keyobs
                .SelectMany(key =>
                    hostCache.GetAndFetchLatestFromIndex(key, () =>
                        apiClient.GetPullRequestsForRepository(repo.CloneUrl.Owner, repo.CloneUrl.RepositoryName)
                                 .Select(PullRequestCacheItem.Create),
                        item =>
                        {
                            // this could blow up due to the collection being disposed somewhere else
                            try { collection.RemoveItem(Create(item)); }
                            catch (ObjectDisposedException) { }
                        },
                        TimeSpan.Zero,
                        TimeSpan.FromDays(7))
                )
                .Select(Create)
            );

            collection.Listen(source);
            return collection;
        }
Ejemplo n.º 48
0
 public IObservable<Unit> UnmarkLocalBranch(ILocalRepositoryModel repository)
 {
     return Observable.Defer(async () =>
     {
         var repo = gitService.GetRepository(repository.LocalPath);
         var configKey = $"branch.{repo.Head.FriendlyName}.ghfvs-pr";
         await gitClient.UnsetConfig(repo, configKey);
         return Observable.Return(Unit.Default);
     });
 }
Ejemplo n.º 49
0
        public IObservable<Unit> SwitchToBranch(ILocalRepositoryModel repository, IPullRequestModel pullRequest)
        {
            return Observable.Defer(async () =>
            {
                var repo = gitService.GetRepository(repository.LocalPath);
                var branchName = GetLocalBranchesInternal(repository, repo, pullRequest).FirstOrDefault();

                Debug.Assert(branchName != null, "PullRequestService.SwitchToBranch called but no local branch found.");

                if (branchName != null)
                {
                    await gitClient.Fetch(repo, "origin");

                    var branch = repo.Branches[branchName];

                    if (branch == null)
                    {
                        var trackedBranchName = $"refs/remotes/origin/" + branchName;
                        var trackedBranch = repo.Branches[trackedBranchName];

                        if (trackedBranch != null)
                        {
                            branch = repo.CreateBranch(branchName, trackedBranch.Tip);
                            await gitClient.SetTrackingBranch(repo, branchName, trackedBranchName);
                        }
                        else
                        {
                            throw new InvalidOperationException($"Could not find branch '{trackedBranchName}'.");
                        }
                    }

                    await gitClient.Checkout(repo, branchName);
                }

                return Observable.Empty<Unit>();
            });
        }
Ejemplo n.º 50
0
 public bool IsPullRequestFromFork(ILocalRepositoryModel repository, IPullRequestModel pullRequest)
 {
     return pullRequest.Head.RepositoryCloneUrl?.ToRepositoryUrl() != repository.CloneUrl.ToRepositoryUrl();
 }
        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);
        }
Ejemplo n.º 52
0
        public IObservable<string> GetDefaultLocalBranchName(ILocalRepositoryModel repository, int pullRequestNumber, string pullRequestTitle)
        {
            return Observable.Defer(() =>
            {
                var initial = "pr/" + pullRequestNumber + "-" + GetSafeBranchName(pullRequestTitle);
                var current = initial;
                var repo = gitService.GetRepository(repository.LocalPath);
                var index = 2;

                while (repo.Branches[current] != null)
                {
                    current = initial + '-' + index++;
                }

                return Observable.Return(current);
            });
        }
 public static IObservable<IConnection> LookupConnection(this IConnectionManager cm, ILocalRepositoryModel repository)
 {
     return Observable.Return(repository?.CloneUrl != null
         ? cm.Connections.FirstOrDefault(c => c.HostAddress.Equals(HostAddress.Create(repository.CloneUrl)))
         : null);
 }
Ejemplo n.º 54
0
 public IObservable<BranchTrackingDetails> CalculateHistoryDivergence(ILocalRepositoryModel repository, int pullRequestNumber)
 {
     return Observable.Defer(async () =>
     {
         var repo = gitService.GetRepository(repository.LocalPath);
         await gitClient.Fetch(repo, repo.Head.Remote.Name);
         return Observable.Return(repo.Head.TrackingDetails);
     });
 }
Ejemplo n.º 55
0
 public IObservable<string> ExtractFile(ILocalRepositoryModel repository, string commitSha, string fileName)
 {
     return Observable.Defer(async () =>
     {
         var repo = gitService.GetRepository(repository.LocalPath);
         await gitClient.Fetch(repo, "origin");
         var result = await gitClient.ExtractFile(repo, commitSha, fileName);
         return Observable.Return(result);
     });
 }
Ejemplo n.º 56
0
 public bool OpenRepository()
 {
     var old = Repositories.FirstOrDefault(x => x.Equals(Holder.ActiveRepo));
     // open the solution selection dialog when the user wants to switch to a different repo
     // since there's no other way of changing the source control context in VS
     if (!Equals(SelectedRepository, old))
     {
         if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().OpenSolutionViaDlg(SelectedRepository.LocalPath, 1)))
         {
             ServiceProvider.TryGetService<ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null);
             return true;
         }
         else
         {
             SelectedRepository = old;
             return false;
         }
     }
     return false;
 }
Ejemplo n.º 57
0
 public IObservable<Tuple<string, string>> ExtractDiffFiles(ILocalRepositoryModel repository, IPullRequestModel pullRequest, string fileName)
 {
     return Observable.Defer(async () =>
     {
         var repo = gitService.GetRepository(repository.LocalPath);
         await gitClient.Fetch(repo, "origin");
         var left = await gitClient.ExtractFile(repo, pullRequest.Base.Sha, fileName);
         var right = await gitClient.ExtractFile(repo, pullRequest.Head.Sha, fileName);
         return Observable.Return(Tuple.Create(left, right));
     });
 }
Ejemplo n.º 58
0
        public IObservable<Unit> RemoteUnusedRemotes(ILocalRepositoryModel repository)
        {
            return Observable.Defer(async () =>
            {
                var repo = gitService.GetRepository(repository.LocalPath);
                var usedRemotes = new HashSet<string>(
                    repo.Branches
                        .Where(x => !x.IsRemote && x.Remote != null)
                        .Select(x => x.Remote?.Name));

                foreach (var remote in repo.Network.Remotes)
                {
                    var key = $"remote.{remote.Name}.{SettingCreatedByGHfVS}";
                    var createdByUs = await gitClient.GetConfig<bool>(repo, key);

                    if (createdByUs && !usedRemotes.Contains(remote.Name))
                    {
                        repo.Network.Remotes.Remove(remote.Name);
                    }
                }

                return Observable.Return(Unit.Default);
            });
        }
Ejemplo n.º 59
0
        public IObservable<Unit> Checkout(ILocalRepositoryModel repository, IPullRequestModel pullRequest, string localBranchName)
        {
            return Observable.Defer(async () =>
            {
                var repo = gitService.GetRepository(repository.LocalPath);
                var existing = repo.Branches[localBranchName];

                if (existing != null)
                {
                    await gitClient.Checkout(repo, localBranchName);
                }
                else if (repository.CloneUrl.ToRepositoryUrl() == pullRequest.Head.RepositoryCloneUrl.ToRepositoryUrl())
                {
                    await gitClient.Fetch(repo, "origin");
                    await gitClient.Checkout(repo, localBranchName);
                }
                else
                {
                    var refSpec = $"{pullRequest.Head.Ref}:{localBranchName}";
                    var prConfigKey = $"branch.{localBranchName}.{SettingGHfVSPullRequest}";
                    var remoteName = await CreateRemote(repo, pullRequest.Head.RepositoryCloneUrl);

                    await gitClient.Fetch(repo, remoteName);
                    await gitClient.Fetch(repo, remoteName, new[] { refSpec });
                    await gitClient.Checkout(repo, localBranchName);
                    await gitClient.SetTrackingBranch(repo, localBranchName, $"refs/remotes/{remoteName}/{pullRequest.Head.Ref}");
                    await gitClient.SetConfig(repo, prConfigKey, pullRequest.Number.ToString());
                }

                return Observable.Return(Unit.Default);
            });
        }
Ejemplo n.º 60
0
 void HandleClonedRepo(ILocalRepositoryModel newrepo)
 {
     var msg = string.Format(CultureInfo.CurrentUICulture, Constants.Notification_RepoCloned, newrepo.Name, newrepo.CloneUrl);
     if (newrepo.HasCommits() && newrepo.MightContainSolution())
         msg += " " + string.Format(CultureInfo.CurrentUICulture, Constants.Notification_OpenProject, newrepo.LocalPath);
     else
         msg += " " + string.Format(CultureInfo.CurrentUICulture, Constants.Notification_CreateNewProject, newrepo.LocalPath);
     ShowNotification(newrepo, msg);
 }