예제 #1
0
 /// <inheritdoc/>
 public async Task <IConnection> GetConnection(HostAddress address)
 {
     return((await GetLoadedConnections()).FirstOrDefault(x => x.HostAddress == address));
 }
예제 #2
0
 public ApiClient(HostAddress hostAddress, IObservableGitHubClient gitHubClient)
 {
     Configure();
     HostAddress       = hostAddress;
     this.gitHubClient = gitHubClient;
 }
 public SimpleCredentialStore(HostAddress hostAddress)
 {
     this.hostAddress = hostAddress;
 }
예제 #4
0
        public virtual async Task <PullRequestDetailModel> ReadPullRequestDetail(HostAddress address, string owner, string name, int number)
        {
            if (readPullRequest == null)
            {
                readPullRequest = new Query()
                                  .Repository(owner: Var(nameof(owner)), name: Var(nameof(name)))
                                  .PullRequest(number: Var(nameof(number)))
                                  .Select(pr => new PullRequestDetailModel
                {
                    Id     = pr.Id.Value,
                    Number = pr.Number,
                    Author = new ActorModel
                    {
                        Login     = pr.Author.Login,
                        AvatarUrl = pr.Author.AvatarUrl(null),
                    },
                    Title               = pr.Title,
                    Body                = pr.Body,
                    BaseRefSha          = pr.BaseRefOid,
                    BaseRefName         = pr.BaseRefName,
                    BaseRepositoryOwner = pr.Repository.Owner.Login,
                    HeadRefName         = pr.HeadRefName,
                    HeadRefSha          = pr.HeadRefOid,
                    HeadRepositoryOwner = pr.HeadRepositoryOwner != null ? pr.HeadRepositoryOwner.Login : null,
                    State               = pr.State.FromGraphQl(),
                    UpdatedAt           = pr.UpdatedAt,
                    CommentCount        = pr.Comments(0, null, null, null).TotalCount,
                    Comments            = pr.Comments(null, null, null, null).AllPages().Select(comment => new CommentModel
                    {
                        Id     = comment.Id.Value,
                        Author = new ActorModel
                        {
                            Login     = comment.Author.Login,
                            AvatarUrl = comment.Author.AvatarUrl(null),
                        },
                        Body       = comment.Body,
                        CreatedAt  = comment.CreatedAt,
                        DatabaseId = comment.DatabaseId.Value,
                        Url        = comment.Url,
                    }).ToList(),
                    Reviews = pr.Reviews(null, null, null, null, null, null).AllPages().Select(review => new PullRequestReviewModel
                    {
                        Id          = review.Id.Value,
                        Body        = review.Body,
                        CommitId    = review.Commit.Oid,
                        State       = review.State.FromGraphQl(),
                        SubmittedAt = review.SubmittedAt,
                        Author      = new ActorModel
                        {
                            Login     = review.Author.Login,
                            AvatarUrl = review.Author.AvatarUrl(null),
                        },
                        Comments = review.Comments(null, null, null, null).AllPages().Select(comment => new CommentAdapter
                        {
                            Id            = comment.Id.Value,
                            PullRequestId = comment.PullRequest.Number,
                            DatabaseId    = comment.DatabaseId.Value,
                            Author        = new ActorModel
                            {
                                Login     = comment.Author.Login,
                                AvatarUrl = comment.Author.AvatarUrl(null),
                            },
                            Body             = comment.Body,
                            Path             = comment.Path,
                            CommitSha        = comment.Commit.Oid,
                            DiffHunk         = comment.DiffHunk,
                            Position         = comment.Position,
                            OriginalPosition = comment.OriginalPosition,
                            OriginalCommitId = comment.OriginalCommit.Oid,
                            ReplyTo          = comment.ReplyTo != null ? comment.ReplyTo.Id.Value : null,
                            CreatedAt        = comment.CreatedAt,
                            Url = comment.Url,
                        }).ToList(),
                    }).ToList(),
                    Timeline = pr.Timeline(null, null, null, null, null).AllPages().Select(item => item.Switch <object>(when =>
                                                                                                                        when.Commit(commit => new CommitModel
                    {
                        AbbreviatedOid = commit.AbbreviatedOid,
                        Author         = new CommitActorModel {
                            Name  = commit.Author.Name,
                            Email = commit.Author.Email,
                            User  = commit.Author.User != null ? new ActorModel
                            {
                                Login     = commit.Author.User.Login,
                                AvatarUrl = commit.Author.User.AvatarUrl(null),
                            } : null
                        },
                        MessageHeadline = commit.MessageHeadline,
                        Oid             = commit.Oid,
                    }).IssueComment(comment => new CommentModel
                    {
                        Author = new ActorModel
                        {
                            Login     = comment.Author.Login,
                            AvatarUrl = comment.Author.AvatarUrl(null),
                        },
                        Body       = comment.Body,
                        CreatedAt  = comment.CreatedAt,
                        DatabaseId = comment.DatabaseId.Value,
                        Id         = comment.Id.Value,
                        Url        = comment.Url,
                    }))).ToList()
                }).Compile();
            }

            var vars = new Dictionary <string, object>
            {
                { nameof(owner), owner },
                { nameof(name), name },
                { nameof(number), number },
            };

            var connection = await graphqlFactory.CreateConnection(address);

            var result = await connection.Run(readPullRequest, vars);

            var apiClient = await apiClientFactory.Create(address);

            var files = await log.TimeAsync(nameof(apiClient.GetPullRequestFiles),
                                            async() => await apiClient.GetPullRequestFiles(owner, name, number).ToList());

            var lastCommitModel = await log.TimeAsync(nameof(GetPullRequestLastCommitAdapter),
                                                      () => GetPullRequestLastCommitAdapter(address, owner, name, number));

            result.Statuses = (IReadOnlyList <StatusModel>)lastCommitModel.Statuses ?? Array.Empty <StatusModel>();

            if (lastCommitModel.CheckSuites == null)
            {
                result.CheckSuites = Array.Empty <CheckSuiteModel>();
            }
            else
            {
                result.CheckSuites = lastCommitModel.CheckSuites;
                foreach (var checkSuite in result.CheckSuites)
                {
                    checkSuite.HeadSha = lastCommitModel.HeadSha;
                }
            }

            result.ChangedFiles = files.Select(file => new PullRequestFileModel
            {
                FileName = file.FileName,
                Sha      = file.Sha,
                Status   = (PullRequestFileStatus)Enum.Parse(typeof(PullRequestFileStatus), file.Status, true),
            }).ToList();

            BuildPullRequestThreads(result);
            return(result);
        }
예제 #5
0
        public virtual async Task <PullRequestDetailModel> ReadPullRequestDetail(HostAddress address, string owner, string name, int number)
        {
            if (readPullRequest == null)
            {
                readPullRequest = new Query()
                                  .Repository(Var(nameof(owner)), Var(nameof(name)))
                                  .PullRequest(Var(nameof(number)))
                                  .Select(pr => new PullRequestDetailModel
                {
                    Id     = pr.Id.Value,
                    Number = pr.Number,
                    Author = new ActorModel
                    {
                        Login     = pr.Author.Login,
                        AvatarUrl = pr.Author.AvatarUrl(null),
                    },
                    Title               = pr.Title,
                    Body                = pr.Body,
                    BaseRefSha          = pr.BaseRefOid,
                    BaseRefName         = pr.BaseRefName,
                    BaseRepositoryOwner = pr.Repository.Owner.Login,
                    HeadRefName         = pr.HeadRefName,
                    HeadRefSha          = pr.HeadRefOid,
                    HeadRepositoryOwner = pr.HeadRepositoryOwner != null ? pr.HeadRepositoryOwner.Login : null,
                    State               = (PullRequestStateEnum)pr.State,
                    UpdatedAt           = pr.UpdatedAt,
                    Reviews             = pr.Reviews(null, null, null, null, null, null).AllPages().Select(review => new PullRequestReviewModel
                    {
                        Id          = review.Id.Value,
                        Body        = review.Body,
                        CommitId    = review.Commit.Oid,
                        State       = (GitHub.Models.PullRequestReviewState)review.State,
                        SubmittedAt = review.SubmittedAt,
                        Author      = new ActorModel
                        {
                            Login     = review.Author.Login,
                            AvatarUrl = review.Author.AvatarUrl(null),
                        },
                        Comments = review.Comments(null, null, null, null).AllPages().Select(comment => new CommentAdapter
                        {
                            Id            = comment.Id.Value,
                            PullRequestId = comment.PullRequest.Number,
                            DatabaseId    = comment.DatabaseId.Value,
                            Author        = new ActorModel
                            {
                                Login     = comment.Author.Login,
                                AvatarUrl = comment.Author.AvatarUrl(null),
                            },
                            Body             = comment.Body,
                            Path             = comment.Path,
                            CommitSha        = comment.Commit.Oid,
                            DiffHunk         = comment.DiffHunk,
                            Position         = comment.Position,
                            OriginalPosition = comment.OriginalPosition,
                            OriginalCommitId = comment.OriginalCommit.Oid,
                            ReplyTo          = comment.ReplyTo != null ? comment.ReplyTo.Id.Value : null,
                            CreatedAt        = comment.CreatedAt,
                            Url = comment.Url,
                        }).ToList(),
                    }).ToList(),
                }).Compile();
            }

            var vars = new Dictionary <string, object>
            {
                { nameof(owner), owner },
                { nameof(name), name },
                { nameof(number), number },
            };

            var connection = await graphqlFactory.CreateConnection(address);

            var result = await connection.Run(readPullRequest, vars);

            var apiClient = await apiClientFactory.Create(address);

            var files = await apiClient.GetPullRequestFiles(owner, name, number).ToList();

            result.ChangedFiles = files.Select(file => new PullRequestFileModel
            {
                FileName = file.FileName,
                Sha      = file.Sha,
                Status   = (PullRequestFileStatus)Enum.Parse(typeof(PullRequestFileStatus), file.Status, true),
            }).ToList();

            BuildPullRequestThreads(result);
            return(result);
        }
예제 #6
0
 public DisconnectedRepositoryHost()
 {
     Address       = HostAddress.Create(new Uri("https://null/"));
     Organizations = new ReactiveList <IAccount>();
     Accounts      = new ReactiveList <IAccount>();
 }
예제 #7
0
        /// <inheritdoc/>
        public async Task <User> Login(
            HostAddress hostAddress,
            IGitHubClient client,
            string userName,
            string password)
        {
            Guard.ArgumentNotNull(hostAddress, nameof(hostAddress));
            Guard.ArgumentNotNull(client, nameof(client));
            Guard.ArgumentNotEmptyString(userName, nameof(userName));
            Guard.ArgumentNotEmptyString(password, nameof(password));

            // Start by saving the username and password, these will be used by the `IGitHubClient`
            // until an authorization token has been created and acquired:
            await keychain.Save(userName, password, hostAddress).ConfigureAwait(false);

            var newAuth = new NewAuthorization
            {
                Scopes      = scopes,
                Note        = authorizationNote,
                Fingerprint = fingerprint,
            };

            ApplicationAuthorization auth = null;

            do
            {
                try
                {
                    auth = await CreateAndDeleteExistingApplicationAuthorization(client, newAuth, null)
                           .ConfigureAwait(false);

                    EnsureNonNullAuthorization(auth);
                }
                catch (TwoFactorAuthorizationException e)
                {
                    auth = await HandleTwoFactorAuthorization(hostAddress, client, newAuth, e)
                           .ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    // Some enterpise instances don't support OAUTH, so fall back to using the
                    // supplied password - on intances that don't support OAUTH the user should
                    // be using a personal access token as the password.
                    if (EnterpriseWorkaround(hostAddress, e))
                    {
                        auth = new ApplicationAuthorization(password);
                    }
                    else
                    {
                        await keychain.Delete(hostAddress).ConfigureAwait(false);

                        throw;
                    }
                }
            } while (auth == null);

            await keychain.Save(userName, auth.Token, hostAddress).ConfigureAwait(false);

            var retry = 0;

            while (true)
            {
                try
                {
                    return(await client.User.Current().ConfigureAwait(false));
                }
                catch (AuthorizationException)
                {
                    if (retry++ == 3)
                    {
                        throw;
                    }
                }

                // It seems that attempting to use a token immediately sometimes fails, retry a few
                // times with a delay of of 1s to allow the token to propagate.
                await Task.Delay(1000);
            }
        }
예제 #8
0
 public static IObservable <bool> IsLoggedIn(this IConnectionManager cm, IRepositoryHosts hosts, HostAddress address)
 {
     return(cm.Connections.ToObservable()
            .Where(c => c.HostAddress.Equals(address))
            .SelectMany(c => c.Login())
            .Any(c => hosts.LookupHost(c.HostAddress).IsLoggedIn));
 }
예제 #9
0
        IConnection SetupConnection(HostAddress address, string username)
        {
            var conn = new Connection(this, address, username);

            return(conn);
        }
예제 #10
0
        public override bool Start()
        {
            Model = DsModel.DS4;

            // skip repairing if disabled in global configuration
            if (!GlobalConfiguration.Instance.Repair)
            {
                return(base.Start());
            }

            var transfered = 0;

            var hostMac = HostAddress.GetAddressBytes();

            byte[] buffer =
            {
                0x13, hostMac[5], hostMac[4], hostMac[3], hostMac[2], hostMac[1], hostMac[0],
                0x00,       0x00,       0x00,       0x00,       0x00,       0x00,       0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            };

            Buffer.BlockCopy(GlobalConfiguration.Instance.BdLink, 0, buffer, 7,
                             GlobalConfiguration.Instance.BdLink.Length);

            if (SendTransfer(UsbHidRequestType.HostToDevice, UsbHidRequest.SetReport, 0x0313, buffer, ref transfered))
            {
                Log.DebugFormat("++ Repaired DS4 [{0}] Link Key For BTH Dongle [{1}]", DeviceAddress.AsFriendlyName(), HostAddress.AsFriendlyName());
            }
            else
            {
                Log.DebugFormat("++ Repair DS4 [{0}] Link Key For BTH Dongle [{1}] Failed!", DeviceAddress.AsFriendlyName(), HostAddress.AsFriendlyName());
            }

            return(base.Start());
        }
예제 #11
0
 public static IObservable <IConnection> LookupConnection(this IConnectionManager cm, ISimpleRepositoryModel repository)
 {
     return(Observable.Return(repository?.CloneUrl != null
         ? cm.Connections.FirstOrDefault(c => c.HostAddress.Equals(HostAddress.Create(repository.CloneUrl)))
         : null));
 }
예제 #12
0
        async Task UpdateContent(ILocalRepositoryModel repository)
        {
            log.Debug("UpdateContent called with {CloneUrl}", repository?.CloneUrl);

            LocalRepository = repository;
            connectionSubscription?.Dispose();
            connectionSubscription = null;
            Connection             = null;
            Content = null;
            navigator.Clear();

            if (repository == null)
            {
                log.Debug("Not a git repository: {CloneUrl}", repository?.CloneUrl);
                Content = notAGitRepository;
                return;
            }
            else if (string.IsNullOrWhiteSpace(repository.CloneUrl))
            {
                log.Debug("Not a GitHub repository: {CloneUrl}", 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 : await client.IsEnterprise();

            var notGitHubRepo = true;

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

                notGitHubRepo = false;

                Connection = await connectionManager.GetConnection(hostAddress);

                Connection?.WhenAnyValue(
                    x => x.IsLoggedIn,
                    x => x.IsLoggingIn,
                    (_, __) => Unit.Default)
                .Skip(1)
                .Throttle(TimeSpan.FromMilliseconds(100))
                .ObserveOn(RxApp.MainThreadScheduler)
                .Subscribe(_ => UpdateContent(LocalRepository).Forget());

                if (Connection?.IsLoggedIn == true)
                {
                    if (await IsValidRepository(client) == true)
                    {
                        log.Debug("Found a GitHub repository: {CloneUrl}", repository?.CloneUrl);
                        Content = navigator;
                        await ShowDefaultPage();
                    }
                    else
                    {
                        notGitHubRepo = true;
                    }
                }
                else if (Connection?.IsLoggingIn == true)
                {
                    log.Debug("Found a GitHub repository: {CloneUrl} and logging in", repository?.CloneUrl);
                    Content = null;
                }
                else if (Connection?.ConnectionError != null)
                {
                    log.Debug("Found a GitHub repository: {CloneUrl} with login error", repository?.CloneUrl);
                    loginFailed.Initialize(Connection.ConnectionError.GetUserFriendlyError(ErrorType.LoginFailed));
                    Content = loginFailed;
                }
                else
                {
                    log.Debug("Found a a GitHub repository but not logged in: {CloneUrl}", repository?.CloneUrl);
                    Content = loggedOut;
                }
            }

            if (notGitHubRepo)
            {
                log.Debug("Not a GitHub repository: {CloneUrl}", repository?.CloneUrl);
                Content = notAGitHubRepository;
            }
        }
예제 #13
0
    public GitHubPaneViewModelTests()
    {
        var repositoryHosts = Substitutes.RepositoryHosts;

        repositoryHosts.IsLoggedInToAnyHost.Returns(true);

        var teamExplorerServiceHolder = Substitute.For <ITeamExplorerServiceHolder>();
        var activeRepo = Substitute.For <ILocalRepositoryModel>();

        activeRepo.CloneUrl.Returns(new UriString("https://github.com/foo/foo"));
        teamExplorerServiceHolder
        .When(x => x.Subscribe(Arg.Any <object>(), Arg.Any <Action <ILocalRepositoryModel> >()))
        .Do(x =>
        {
            var invokeAction = x.Arg <Action <ILocalRepositoryModel> >();
            invokeAction(activeRepo);
        });

        var connectionManager     = Substitutes.ConnectionManager;
        var connection            = Substitutes.Connection;
        var connectionHostAddress = HostAddress.Create(activeRepo.CloneUrl.ToString());

        connection.HostAddress.Returns(connectionHostAddress);
        connectionManager.Connections.Returns(new ObservableCollection <IConnection>(new[] {
            connection
        }));
        connection.Login().Returns(Observable.Return(connection));

        var host = Substitute.For <IRepositoryHost>();

        host.IsLoggedIn.Returns(true);
        repositoryHosts.LookupHost(connectionHostAddress).Returns(host);

        serviceProvider    = Substitutes.GetFullyMockedServiceProvider();
        menuCommandService = new FakeMenuCommandService();
        serviceProvider.GetService(typeof(IMenuCommandService)).Returns(menuCommandService);

        var uiProvider = serviceProvider as IUIProvider;

        uiProvider.TryGetService(typeof(IUIProvider)).Returns(serviceProvider);

        uiController = Substitute.For <IUIController>();
        uiController.CurrentFlow.Returns(UIControllerFlow.PullRequests);
        uiController.SelectedFlow.Returns(UIControllerFlow.PullRequests);
        uiController
        .When(x => x.Jump(Arg.Any <ViewWithData>()))
        .Do(x => lastUiControllerJump = x.Arg <ViewWithData>().ViewType);

        var exportFactoryProvider = Substitutes.ExportFactoryProvider;

        uiProvider.TryGetService(typeof(IExportFactoryProvider)).Returns(exportFactoryProvider);
        exportFactoryProvider.UIControllerFactory.Returns(new ExportFactory <IUIController>(
                                                              () => Tuple.Create <IUIController, Action>(uiController, () => { })));

        viewModel = new GitHubPaneViewModel(
            Substitute.For <ISimpleApiClientFactory>(),
            teamExplorerServiceHolder,
            connectionManager,
            repositoryHosts,
            Substitute.For <INotificationDispatcher>());

        viewModel.ActiveRepo = activeRepo;
    }
예제 #14
0
 static ConnectionDetails FromCache(ConnectionCacheItem c)
 {
     return(new ConnectionDetails(HostAddress.Create(c.HostUrl), c.UserName));
 }
        public async Task <Page <PullRequestListItemModel> > ReadPullRequests(
            HostAddress address,
            string owner,
            string name,
            string after,
            PullRequestStateEnum[] states)
        {
            ICompiledQuery <Page <PullRequestListItemModel> > query;

            if (address.IsGitHubDotCom())
            {
                if (readPullRequests == null)
                {
                    readPullRequests = new Query()
                                       .Repository(Var(nameof(owner)), Var(nameof(name)))
                                       .PullRequests(
                        first: 100,
                        after: Var(nameof(after)),
                        orderBy: new IssueOrder {
                        Direction = OrderDirection.Desc, Field = IssueOrderField.CreatedAt
                    },
                        states: Var(nameof(states)))
                                       .Select(page => new Page <PullRequestListItemModel>
                    {
                        EndCursor   = page.PageInfo.EndCursor,
                        HasNextPage = page.PageInfo.HasNextPage,
                        TotalCount  = page.TotalCount,
                        Items       = page.Nodes.Select(pr => new ListItemAdapter
                        {
                            Id         = pr.Id.Value,
                            LastCommit = pr.Commits(null, null, 1, null).Nodes.Select(commit =>
                                                                                      new LastCommitSummaryAdapter
                            {
                                CheckSuites = commit.Commit.CheckSuites(null, null, null, null, null).AllPages(10)
                                              .Select(suite => new CheckSuiteSummaryModel
                                {
                                    CheckRuns = suite.CheckRuns(null, null, null, null, null).AllPages(10)
                                                .Select(run => new CheckRunSummaryModel
                                    {
                                        Conclusion = run.Conclusion.FromGraphQl(),
                                        Status     = run.Status.FromGraphQl()
                                    }).ToList(),
                                }).ToList(),
                                Statuses = commit.Commit.Status
                                           .Select(context =>
                                                   context.Contexts.Select(statusContext => new StatusSummaryModel
                                {
                                    State = statusContext.State.FromGraphQl(),
                                }).ToList()
                                                   ).SingleOrDefault()
                            }).ToList().FirstOrDefault(),
                            Author = new ActorModel
                            {
                                Login     = pr.Author.Login,
                                AvatarUrl = pr.Author.AvatarUrl(null),
                            },
                            CommentCount = pr.Comments(0, null, null, null).TotalCount,
                            Number       = pr.Number,
                            Reviews      = pr.Reviews(null, null, null, null, null, null).AllPages().Select(review => new ReviewAdapter
                            {
                                Body         = review.Body,
                                CommentCount = review.Comments(null, null, null, null).TotalCount,
                            }).ToList(),
                            State     = pr.State.FromGraphQl(),
                            Title     = pr.Title,
                            UpdatedAt = pr.UpdatedAt,
                        }).ToList(),
                    }).Compile();
                }

                query = readPullRequests;
            }
            else
            {
                if (readPullRequestsEnterprise == null)
                {
                    readPullRequestsEnterprise = new Query()
                                                 .Repository(Var(nameof(owner)), Var(nameof(name)))
                                                 .PullRequests(
                        first: 100,
                        after: Var(nameof(after)),
                        orderBy: new IssueOrder {
                        Direction = OrderDirection.Desc, Field = IssueOrderField.CreatedAt
                    },
                        states: Var(nameof(states)))
                                                 .Select(page => new Page <PullRequestListItemModel>
                    {
                        EndCursor   = page.PageInfo.EndCursor,
                        HasNextPage = page.PageInfo.HasNextPage,
                        TotalCount  = page.TotalCount,
                        Items       = page.Nodes.Select(pr => new ListItemAdapter
                        {
                            Id         = pr.Id.Value,
                            LastCommit = pr.Commits(null, null, 1, null).Nodes.Select(commit =>
                                                                                      new LastCommitSummaryAdapter
                            {
                                Statuses = commit.Commit.Status.Select(context =>
                                                                       context == null
                                                          ? null
                                                          : context.Contexts
                                                                       .Select(statusContext => new StatusSummaryModel
                                {
                                    State = statusContext.State.FromGraphQl()
                                }).ToList()
                                                                       ).SingleOrDefault()
                            }).ToList().FirstOrDefault(),
                            Author = new ActorModel
                            {
                                Login     = pr.Author.Login,
                                AvatarUrl = pr.Author.AvatarUrl(null),
                            },
                            CommentCount = pr.Comments(0, null, null, null).TotalCount,
                            Number       = pr.Number,
                            Reviews      = pr.Reviews(null, null, null, null, null, null).AllPages().Select(review => new ReviewAdapter
                            {
                                Body         = review.Body,
                                CommentCount = review.Comments(null, null, null, null).TotalCount,
                            }).ToList(),
                            State     = pr.State.FromGraphQl(),
                            Title     = pr.Title,
                            UpdatedAt = pr.UpdatedAt,
                        }).ToList(),
                    }).Compile();
                }

                query = readPullRequestsEnterprise;
            }

            var graphql = await graphqlFactory.CreateConnection(address);

            var vars = new Dictionary <string, object>
            {
                { nameof(owner), owner },
                { nameof(name), name },
                { nameof(after), after },
                { nameof(states), states.Select(x => (PullRequestState)x).ToList() },
            };

            var result = await graphql.Run(query, vars);

            foreach (var item in result.Items.Cast <ListItemAdapter>())
            {
                item.CommentCount += item.Reviews.Sum(x => x.Count);
                item.Reviews       = null;

                var checkRuns = item.LastCommit?.CheckSuites?.SelectMany(model => model.CheckRuns).ToArray();

                var hasCheckRuns = checkRuns?.Any() ?? false;
                var hasStatuses  = item.LastCommit?.Statuses?.Any() ?? false;

                if (!hasCheckRuns && !hasStatuses)
                {
                    item.Checks = PullRequestChecksState.None;
                }
                else
                {
                    var checksHasFailure         = false;
                    var checksHasCompleteSuccess = true;

                    if (hasCheckRuns)
                    {
                        checksHasFailure = checkRuns
                                           .Any(model => model.Conclusion.HasValue &&
                                                (model.Conclusion.Value == CheckConclusionState.Failure ||
                                                 model.Conclusion.Value == CheckConclusionState.ActionRequired));

                        if (!checksHasFailure)
                        {
                            checksHasCompleteSuccess = checkRuns
                                                       .All(model => model.Conclusion.HasValue &&
                                                            (model.Conclusion.Value == CheckConclusionState.Success ||
                                                             model.Conclusion.Value == CheckConclusionState.Neutral));
                        }
                    }

                    var statusHasFailure         = false;
                    var statusHasCompleteSuccess = true;

                    if (!checksHasFailure && hasStatuses)
                    {
                        statusHasFailure = item.LastCommit
                                           .Statuses
                                           .Any(status => status.State == StatusState.Failure ||
                                                status.State == StatusState.Error);

                        if (!statusHasFailure)
                        {
                            statusHasCompleteSuccess =
                                item.LastCommit.Statuses.All(status => status.State == StatusState.Success);
                        }
                    }

                    if (checksHasFailure || statusHasFailure)
                    {
                        item.Checks = PullRequestChecksState.Failure;
                    }
                    else if (statusHasCompleteSuccess && checksHasCompleteSuccess)
                    {
                        item.Checks = PullRequestChecksState.Success;
                    }
                    else
                    {
                        item.Checks = PullRequestChecksState.Pending;
                    }
                }

                item.LastCommit = null;
            }

            return(result);
        }
예제 #16
0
 public IConnection CreateConnection(HostAddress address, string username)
 {
     return(SetupConnection(address, username));
 }
예제 #17
0
        protected void StartFlow(UIControllerFlow controllerFlow)
        {
            IConnection connection = null;

            if (controllerFlow != UIControllerFlow.Authentication)
            {
                var activeRepo = GetActiveRepo();
                connection = ServiceProvider.TryGetService <IConnectionManager>()?.Connections
                             .FirstOrDefault(c => activeRepo?.CloneUrl?.RepositoryName != null && c.HostAddress.Equals(HostAddress.Create(activeRepo.CloneUrl)));
            }
            ServiceProvider.TryGetService <IUIProvider>().RunInDialog(controllerFlow, connection);
        }
예제 #18
0
        public async Task RefreshRepositories()
        {
            var list = await Task.Run(() => vsGitServices.GetKnownRepositories());

            list.GroupBy(r => Connections.FirstOrDefault(c => r.CloneUrl != null && c.HostAddress.Equals(HostAddress.Create(r.CloneUrl))))
            .Where(g => g.Key != null)
            .ForEach(g =>
            {
                var repos = g.Key.Repositories;
                repos.Except(g).ToList().ForEach(c => repos.Remove(c));
                g.Except(repos).ToList().ForEach(c => repos.Add(c));
            });
        }
 protected override IObservable <AuthenticationResult> LogIn(object args)
 {
     return(LogInToHost(HostAddress.Create(EnterpriseUrl)));
 }
        public async Task SavesConnectionToCache()
        {
            var cache  = CreateConnectionCache();
            var target = new ConnectionManager(
                CreateProgram(),
                cache,
                Substitute.For <IKeychain>(),
                CreateLoginManager(),
                Substitute.For <IUsageTracker>());

            await target.LogIn(HostAddress.GitHubDotComHostAddress, "user", "pass");

            await cache.Received(1).Save(Arg.Is <IEnumerable <ConnectionDetails> >(x =>
                                                                                   x.Count() == 1 && x.ElementAt(0).HostAddress == HostAddress.Create("https://github.com")));
        }
예제 #21
0
 protected override Task <IConnection> LogInViaOAuth(object args)
 {
     return(LoginToHostViaOAuth(HostAddress.Create(EnterpriseUrl)));
 }
예제 #22
0
 public IObservable <LoginInfo> GetLoginAsync(HostAddress hostAddress)
 {
     return(loginCacheDelegate.GetLoginAsync(hostAddress));
 }
예제 #23
0
        async Task <LastCommitAdapter> GetPullRequestLastCommitAdapter(HostAddress address, string owner, string name, int number)
        {
            ICompiledQuery <IEnumerable <LastCommitAdapter> > query;

            if (address.IsGitHubDotCom())
            {
                if (readCommitStatuses == null)
                {
                    readCommitStatuses = new Query()
                                         .Repository(owner: Var(nameof(owner)), name: Var(nameof(name)))
                                         .PullRequest(number: Var(nameof(number))).Commits(last: 1).Nodes.Select(
                        commit => new LastCommitAdapter
                    {
                        HeadSha     = commit.Commit.Oid,
                        CheckSuites = commit.Commit.CheckSuites(null, null, null, null, null).AllPages(10)
                                      .Select(suite => new CheckSuiteModel
                        {
                            CheckRuns = suite.CheckRuns(null, null, null, null, null).AllPages(10)
                                        .Select(run => new CheckRunModel
                            {
                                Id          = run.Id.Value,
                                Conclusion  = run.Conclusion.FromGraphQl(),
                                Status      = run.Status.FromGraphQl(),
                                Name        = run.Name,
                                DetailsUrl  = run.Permalink,
                                Summary     = run.Summary,
                                Text        = run.Text,
                                Annotations = run.Annotations(null, null, null, null).AllPages()
                                              .Select(annotation => new CheckRunAnnotationModel
                                {
                                    Title           = annotation.Title,
                                    Message         = annotation.Message,
                                    Path            = annotation.Path,
                                    AnnotationLevel = annotation.AnnotationLevel.Value.FromGraphQl(),
                                    StartLine       = annotation.Location.Start.Line,
                                    EndLine         = annotation.Location.End.Line,
                                }).ToList()
                            }).ToList(),
                            ApplicationName = suite.App != null ? suite.App.Name : "Private App"
                        }).ToList(),
                        Statuses = commit.Commit.Status
                                   .Select(context =>
                                           context.Contexts.Select(statusContext => new StatusModel
                        {
                            State       = statusContext.State.FromGraphQl(),
                            Context     = statusContext.Context,
                            TargetUrl   = statusContext.TargetUrl,
                            Description = statusContext.Description
                        }).ToList()
                                           ).SingleOrDefault()
                    }
                        ).Compile();
                }

                query = readCommitStatuses;
            }
            else
            {
                if (readCommitStatusesEnterprise == null)
                {
                    readCommitStatusesEnterprise = new Query()
                                                   .Repository(owner: Var(nameof(owner)), name: Var(nameof(name)))
                                                   .PullRequest(number: Var(nameof(number))).Commits(last: 1).Nodes.Select(
                        commit => new LastCommitAdapter
                    {
                        Statuses = commit.Commit.Status == null ? null : commit.Commit.Status
                                   .Select(context => context == null
                                     ? null
                                     : context.Contexts
                                           .Select(statusContext => new StatusModel
                        {
                            State       = statusContext.State.FromGraphQl(),
                            Context     = statusContext.Context,
                            TargetUrl   = statusContext.TargetUrl,
                            Description = statusContext.Description,
                        }).ToList()
                                           ).SingleOrDefault()
                    }
                        ).Compile();
                }

                query = readCommitStatusesEnterprise;
            }

            var vars = new Dictionary <string, object>
            {
                { nameof(owner), owner },
                { nameof(name), name },
                { nameof(number), number },
            };

            var connection = await graphqlFactory.CreateConnection(address);

            var result = await connection.Run(query, vars);

            return(result.First());
        }
예제 #24
0
 public IObservable <Unit> SaveLogin(string user, string password, HostAddress hostAddress)
 {
     return(loginCacheDelegate.SaveLogin(user, password, hostAddress));
 }
예제 #25
0
        public IObservable <AutoCompleteSuggestion> GetSuggestions()
        {
            var localRepositoryModel = teamExplorerContext.ActiveRepository;

            var hostAddress = HostAddress.Create(localRepositoryModel.CloneUrl.Host);
            var owner       = localRepositoryModel.Owner;
            var name        = localRepositoryModel.Name;

            string filter;
            string after;

            if (query == null)
            {
                query = new Query().Search(query: Var(nameof(filter)), SearchType.Issue, 100, after: Var(nameof(after)))
                        .Select(item => new Page <SuggestionItem>
                {
                    Items = item.Nodes.Select(searchResultItem =>
                                              searchResultItem.Switch <SuggestionItem>(selector => selector
                                                                                       .Issue(i => new SuggestionItem("#" + i.Number, i.Title)
                    {
                        LastModifiedDate = i.LastEditedAt
                    })
                                                                                       .PullRequest(p => new SuggestionItem("#" + p.Number, p.Title)
                    {
                        LastModifiedDate = p.LastEditedAt
                    }))
                                              ).ToList(),
                    EndCursor   = item.PageInfo.EndCursor,
                    HasNextPage = item.PageInfo.HasNextPage,
                    TotalCount  = item.IssueCount
                })
                        .Compile();
            }

            filter = $"repo:{owner}/{name}";

            return(Observable.FromAsync(async() =>
            {
                var results = new List <SuggestionItem>();

                var variables = new Dictionary <string, object>
                {
                    { nameof(filter), filter },
                };

                var connection = await graphqlFactory.CreateConnection(hostAddress);
                var searchResults = await connection.Run(query, variables);

                results.AddRange(searchResults.Items);

                while (searchResults.HasNextPage)
                {
                    variables[nameof(after)] = searchResults.EndCursor;
                    searchResults = await connection.Run(query, variables);

                    results.AddRange(searchResults.Items);
                }

                return results.Select(item => new IssueAutoCompleteSuggestion(item, Prefix));
            }).SelectMany(observable => observable));
        }
예제 #26
0
 public IObservable <Unit> EraseLogin(HostAddress hostAddress)
 {
     return(loginCacheDelegate.EraseLogin(hostAddress));
 }
    static TestData PrepareTestData(
        string repoName, string sourceRepoOwner, string sourceBranchName,
        string targetRepoOwner, string targetBranchName,
        string remote,
        bool repoIsFork, bool sourceBranchIsTracking)
    {
        var serviceProvider = Substitutes.ServiceProvider;
        var gitService      = serviceProvider.GetGitService();
        var gitClient       = Substitute.For <IGitClient>();
        var notifications   = Substitute.For <INotificationService>();
        var connection      = Substitute.For <IConnection>();
        var api             = Substitute.For <IApiClient>();
        var ms = Substitute.For <IModelService>();
        var autoCompleteAdvisor = Substitute.For <IAutoCompleteAdvisor>();

        connection.HostAddress.Returns(HostAddress.Create("https://github.com"));

        var activeRepo = new LocalRepositoryModel
        {
            LocalPath = "",
            Name      = repoName,
            CloneUrl  = new UriString("http://github.com/" + sourceRepoOwner + "/" + repoName)
        };

        Repository githubRepoParent = null;

        if (repoIsFork)
        {
            githubRepoParent = CreateRepository(targetRepoOwner, repoName, id: 1);
        }
        var githubRepo   = CreateRepository(sourceRepoOwner, repoName, id: 2, parent: githubRepoParent);
        var sourceBranch = new BranchModel(sourceBranchName, activeRepo);
        var sourceRepo   = CreateRemoteRepositoryModel(githubRepo);
        var targetRepo   = targetRepoOwner == sourceRepoOwner ? sourceRepo : sourceRepo.Parent;
        var targetBranch = targetBranchName != targetRepo.DefaultBranch.Name ? new BranchModel(targetBranchName, targetRepo) : targetRepo.DefaultBranch;

        gitService.GetBranch(activeRepo).Returns(sourceBranch);
        api.GetRepository(Args.String, Args.String).Returns(Observable.Return(githubRepo));
        ms.ApiClient.Returns(api);

        // Default to returning no branches
        ms.GetBranches(null).ReturnsForAnyArgs(Observable.Empty <BranchModel>());

        // sets up the libgit2sharp repo and branch objects
        var l2repo = SetupLocalRepoMock(gitClient, gitService, remote, sourceBranchName, sourceBranchIsTracking);

        return(new TestData
        {
            ServiceProvider = serviceProvider,
            ActiveRepo = activeRepo,
            L2Repo = l2repo,
            SourceRepo = sourceRepo,
            SourceBranch = sourceBranch,
            TargetRepo = targetRepo,
            TargetBranch = targetBranch,
            GitClient = gitClient,
            GitService = gitService,
            NotificationService = notifications,
            Connection = connection,
            ApiClient = api,
            ModelService = ms,
            AutoCompleteAdvisor = autoCompleteAdvisor
        });
    }
        async Task <LastCommitAdapter> GetPullRequestLastCommitAdapter(HostAddress address, string owner, string name, int number)
        {
            ICompiledQuery <IEnumerable <LastCommitAdapter> > query;

            if (address.IsGitHubDotCom())
            {
                if (readCommitStatuses == null)
                {
                    readCommitStatuses = new Query()
                                         .Repository(Var(nameof(owner)), Var(nameof(name)))
                                         .PullRequest(Var(nameof(number))).Commits(last: 1).Nodes.Select(
                        commit => new LastCommitAdapter
                    {
                        CheckSuites = commit.Commit.CheckSuites(null, null, null, null, null).AllPages(10)
                                      .Select(suite => new CheckSuiteModel
                        {
                            CheckRuns = suite.CheckRuns(null, null, null, null, null).AllPages(10)
                                        .Select(run => new CheckRunModel
                            {
                                Conclusion = run.Conclusion.FromGraphQl(),
                                Status     = run.Status.FromGraphQl(),
                                Name       = run.Name,
                                DetailsUrl = run.Permalink,
                                Summary    = run.Summary,
                            }).ToList()
                        }).ToList(),
                        Statuses = commit.Commit.Status
                                   .Select(context =>
                                           context.Contexts.Select(statusContext => new StatusModel
                        {
                            State       = statusContext.State.FromGraphQl(),
                            Context     = statusContext.Context,
                            TargetUrl   = statusContext.TargetUrl,
                            Description = statusContext.Description,
                        }).ToList()
                                           ).SingleOrDefault()
                    }
                        ).Compile();
                }

                query = readCommitStatuses;
            }
            else
            {
                if (readCommitStatusesEnterprise == null)
                {
                    readCommitStatusesEnterprise = new Query()
                                                   .Repository(Var(nameof(owner)), Var(nameof(name)))
                                                   .PullRequest(Var(nameof(number))).Commits(last: 1).Nodes.Select(
                        commit => new LastCommitAdapter
                    {
                        Statuses = commit.Commit.Status
                                   .Select(context =>
                                           context.Contexts.Select(statusContext => new StatusModel
                        {
                            State       = statusContext.State.FromGraphQl(),
                            Context     = statusContext.Context,
                            TargetUrl   = statusContext.TargetUrl,
                            Description = statusContext.Description,
                        }).ToList()
                                           ).SingleOrDefault()
                    }
                        ).Compile();
                }

                query = readCommitStatusesEnterprise;
            }

            var vars = new Dictionary <string, object>
            {
                { nameof(owner), owner },
                { nameof(name), name },
                { nameof(number), number },
            };

            var connection = await graphqlFactory.CreateConnection(address);

            var result = await connection.Run(query, vars);

            return(result.First());
        }
예제 #29
0
        /// <inheritdoc/>
        public async Task <LoginResult> Login(
            HostAddress hostAddress,
            IGitHubClient client,
            string userName,
            string password)
        {
            Guard.ArgumentNotNull(hostAddress, nameof(hostAddress));
            Guard.ArgumentNotNull(client, nameof(client));
            Guard.ArgumentNotEmptyString(userName, nameof(userName));
            Guard.ArgumentNotEmptyString(password, nameof(password));

            // Start by saving the username and password, these will be used by the `IGitHubClient`
            // until an authorization token has been created and acquired:
            await keychain.Save(userName, password, hostAddress).ConfigureAwait(false);

            var newAuth = new NewAuthorization
            {
                Scopes      = requestedScopes,
                Note        = authorizationNote,
                Fingerprint = fingerprint,
            };

            ApplicationAuthorization auth = null;

            do
            {
                try
                {
                    auth = await CreateAndDeleteExistingApplicationAuthorization(client, newAuth, null)
                           .ConfigureAwait(false);

                    EnsureNonNullAuthorization(auth);
                }
                catch (TwoFactorAuthorizationException e)
                {
                    auth = await HandleTwoFactorAuthorization(hostAddress, client, newAuth, e)
                           .ConfigureAwait(false);
                }
                catch (Exception e)
                {
                    // Some enterpise instances don't support OAUTH, so fall back to using the
                    // supplied password - on intances that don't support OAUTH the user should
                    // be using a personal access token as the password.
                    if (EnterpriseWorkaround(hostAddress, e))
                    {
                        auth = new ApplicationAuthorization(0,
                                                            null, null, null, null, null, null, null,
                                                            DateTimeOffset.MinValue, DateTimeOffset.MinValue, null, password);
                    }
                    else
                    {
                        await keychain.Delete(hostAddress).ConfigureAwait(false);

                        throw;
                    }
                }
            } while (auth == null);

            await keychain.Save(userName, auth.Token, hostAddress).ConfigureAwait(false);

            return(await ReadUserWithRetry(client).ConfigureAwait(false));
        }
        Task <IApiClient> CreateApiClient(ILocalRepositoryModel repository)
        {
            var hostAddress = HostAddress.Create(repository.CloneUrl.Host);

            return(apiClientFactory.Create(hostAddress));
        }