Exemple #1
0
        public async Task <IntegrationBranchResult> FindSingleIntegrationBranch(BranchGroupCompleteData details, string groupName, AttemptMergeDelegate doMerge)
        {
            var groups = new[] { details.GroupName, groupName }.OrderBy(g => g).ToArray();
            var integrationBranch = await settings.FindIntegrationBranchForConflict(groups[0], groups[1], groups.ToImmutableList());

            if (integrationBranch == null)
            {
                return(new IntegrationBranchResult
                {
                    AddedBranches = Enumerable.Empty <string>(),
                });
            }

            await doMerge(integrationBranch, details.LatestBranchName, $"Auto-merge branch '{integrationBranch}'");

#pragma warning disable CS4014
            orchestration.EnqueueAction(new ConsolidateMergedAction(integrationBranch, details.GroupName));
#pragma warning restore

            return(new IntegrationBranchResult
            {
                Resolved = true,
                AddedBranches = new[] { integrationBranch },
            });
        }
            private async Task <bool> MergesInProgress(BranchGroupCompleteData targetBranch, ImmutableList <BranchGroupCompleteData> branchesToRemove)
            {
                var actions = await orchestration.ActionQueue.FirstOrDefaultAsync();

                var removingNames = branchesToRemove.Select(b => b.GroupName).ToImmutableHashSet();

                return(actions.OfType <MergeDownstreamAction>()
                       .Where(a => targetBranch.UpstreamBranchGroups.Contains(a.DownstreamBranch) || a.DownstreamBranch == targetBranch.GroupName || removingNames.Contains(a.DownstreamBranch))
                       .Any());
            }
        private BranchGroupCompleteData AddRemoteBranchNames(BranchGroupCompleteData branchDetails, ImmutableList <GitRef> remoteBranches)
        {
            var names = remoteBranches.Where(remoteBranch => branchIteration.IsBranchIteration(branchDetails.GroupName, remoteBranch.Name)).ToImmutableList();

            return(new BranchGroupCompleteData(branchDetails)
            {
                Branches = names,
                LatestBranchName = names.Count == 0 ? null : branchIteration.GetLatestBranchNameIteration(branchDetails.GroupName, names.Select(b => b.Name)),
            });
        }
        public async Task <bool> AddAdditionalIntegrationBranches(BranchGroupCompleteData details, IUnitOfWork unitOfWork)
        {
            var branches = await branchSettings.GetIntegrationBranches(details.UpstreamBranchGroups);

            var toAdd = branches.Except(details.UpstreamBranchGroups).Except(new [] { details.GroupName }).ToImmutableList();

            if (toAdd.Any())
            {
                foreach (var upstreamBranch in toAdd)
                {
                    branchSettings.AddBranchPropagation(upstreamBranch, details.GroupName, unitOfWork);
                }
                return(true);
            }
            return(false);
        }
 private IObservable <(BranchGroupCompleteData branch, string latestBranchName)> GetLatestBranchTuple(BranchGroupCompleteData branch)
 {
     return(from latestBranchName in repository.LatestBranchName(branch).FirstOrDefaultAsync()
            select(branch, latestBranchName));
 }
            private async Task <ImmutableList <BranchGroupCompleteData> > GetBranchesToRemove(BranchGroupCompleteData targetBranch)
            {
                if (targetBranch.DirectDownstreamBranchGroups.Contains(newBaseBranch))
                {
                    // We're deleting an old branch, and all of its stuff moves down. This is like an integration branch rolling up. Easy.
                    return(new[] { targetBranch }.ToImmutableList());
                }
                var allBranches = await repository.AllBranches().FirstOrDefaultAsync();

                var actualBranches = await repository.DetectUpstream(sourceBranch);

                var upstreamBranches = await branchSettings.GetAllUpstreamBranches(sourceBranch).FirstAsync();

                // Filter to only the actual upstream branches; don't just remove anything that is downstream and happens to match!
                actualBranches = actualBranches.Intersect(upstreamBranches.Select(b => b.GroupName)).ToImmutableList();

                // FIXME - this is the _branches_ not the _groups_ that are up-to-date. That should be okay for these purposes.
                var downstream = (await branchSettings.GetBranchDetails(newBaseBranch).FirstAsync()).DownstreamBranchGroups;

                var consolidatingBranches = (await(from branch in allBranches.ToObservable()
                                                   where actualBranches.Contains(branch.GroupName) || branch.Branches.Select(b => b.Name).Any(actualBranches.Contains)
                                                   where downstream.Contains(branch.GroupName)
                                                   from result in GetLatestBranchTuple(branch)
                                                   select result
                                                   ).ToArray()).ToImmutableHashSet();


                var branchesToRemove = await FindReadyToConsolidate(consolidatingBranches);

                branchesToRemove = branchesToRemove.Concat(allBranches.Where(g => g.Branches.Select(b => b.Name).Contains(sourceBranch))).ToImmutableList();
                return(branchesToRemove);
            }
Exemple #7
0
        public async Task <IntegrationBranchResult> FindAndCreateIntegrationBranches(BranchGroupCompleteData downstreamDetails, IEnumerable <string> initialUpstreamBranchGroups, AttemptMergeDelegate doMerge)
        {
            // 1. Find branches that conflict
            // 2. Create integration branches for them
            // 3. Add the integration branch for ourselves

            foreach (var upstream in initialUpstreamBranchGroups)
            {
                if (await repository.IsBadBranch(upstream))
                {
                    // A branch that was directly upstream had updates pending
                    return(new IntegrationBranchResult {
                        PendingUpdates = true
                    });
                }
            }

            var result = await FindConflicts(downstreamDetails.GroupName, initialUpstreamBranchGroups, doMerge);

            if (result.PendingUpdates)
            {
                return(result);
            }

            var newIntegrationBranches = new List <string>();

            using (var work = workFactory.CreateUnitOfWork())
            {
                foreach (var conflict in result.Conflicts)
                {
                    // I need an integration branch!
                    var integrationBranch = await settings.FindIntegrationBranchForConflict(conflict.BranchA.GroupName, conflict.BranchB.GroupName, downstreamDetails.UpstreamBranchGroups);

                    if (downstreamDetails.UpstreamBranchGroups.Contains(integrationBranch))
                    {
                        // You already have one! - Maz Kanata
                        continue;
                    }
                    var originalIntegrationBranch = integrationBranch;
                    if (integrationBranch == null)
                    {
                        if (conflict.BranchA.GroupName == downstreamDetails.GroupName || conflict.BranchB.GroupName == downstreamDetails.GroupName)
                        {
                            continue;
                        }
                        integrationBranch = await integrationNaming.GetIntegrationBranchName(conflict.BranchA.GroupName, conflict.BranchB.GroupName);

                        settings.CreateIntegrationBranch(conflict.BranchA.GroupName, conflict.BranchB.GroupName, integrationBranch, work);
#pragma warning disable CS4014
                        orchestration.EnqueueAction(new MergeDownstreamAction(integrationBranch));
#pragma warning restore
                    }
                    if (originalIntegrationBranch != null && (conflict.BranchA.GroupName == downstreamDetails.GroupName || conflict.BranchB.GroupName == downstreamDetails.GroupName))
                    {
                        // There was an integration branch with the current branch and an upstream branch. Flip it around and consolidate!
                        newIntegrationBranches.Add(integrationBranch);
                        settings.AddBranchPropagation(integrationBranch, downstreamDetails.GroupName, work);
                        settings.RemoveBranchPropagation(downstreamDetails.GroupName, integrationBranch, work);

#pragma warning disable CS4014
                        orchestration.EnqueueAction(new MergeDownstreamAction(downstreamDetails.GroupName));
                        orchestration.EnqueueAction(new ConsolidateMergedAction(integrationBranch, downstreamDetails.GroupName));
#pragma warning restore
                    }
                    else if (!downstreamDetails.UpstreamBranchGroups.Any(b => b == integrationBranch))
                    {
                        newIntegrationBranches.Add(integrationBranch);
                        settings.AddBranchPropagation(integrationBranch, downstreamDetails.GroupName, work);
                    }
                }
                await work.CommitAsync();
            }

            return(new IntegrationBranchResult
            {
                Conflicts = result.Conflicts,
                AddedBranches = newIntegrationBranches,
            });
        }