private async System.Threading.Tasks.Task <ImmutableList <string> > PruneUpstream(GitRef original, ImmutableList <GitRef> allUpstream, ImmutableList <BranchGroup> configured, ImmutableList <GitRef> allRemotes) { var configuredLatest = configured.ToDictionary(branch => branch.GroupName, branch => branchIteration.GetLatestBranchNameIteration(branch.GroupName, allRemotes.Select(b => b.Name))); allUpstream = allUpstream.Where(maybeHasNewer => !configured.Any(c => branchIteration.IsBranchIteration(c.GroupName, maybeHasNewer.Name) && maybeHasNewer.Name != configuredLatest[c.GroupName]) ).ToImmutableList(); for (var i = 0; i < allUpstream.Count; i++) { var upstream = allUpstream[i]; var isConfigured = configuredLatest.Values.Contains(upstream.Name); var furtherUpstream = (from branchGroup in (await branchSettings.GetAllUpstreamBranches(upstream.Name).FirstOrDefaultAsync()) let latest = configuredLatest[branchGroup.GroupName] where allRemotes.Find(b => b.Name == latest).Commit != upstream.Commit select latest) .ToImmutableHashSet(); var oldLength = allUpstream.Count; allUpstream = allUpstream.Where(maybeMatch => !furtherUpstream.Contains(maybeMatch.Name)).ToImmutableList(); if (oldLength != allUpstream.Count) { i = -1; } } // TODO - this could be much smarter for (var i = 0; i < allUpstream.Count; i++) { var upstream = allUpstream[i]; var furtherUpstream = await repositoryState.DetectUpstream(upstream.Name, false); if (allUpstream.Intersect(furtherUpstream).Any()) { allUpstream = allUpstream.Except(furtherUpstream).ToImmutableList(); i = -1; } } return(allUpstream.Select(b => b.Name).ToImmutableList()); }
protected override async Task RunProcess() { if (isReadOnly) { return; } // either: // 1. create new service line from release candidate // 2. merge --ff-only from release candidate to service line // if it passes: // collect upstream branches // push service line var upstreamLines = await repository.DetectShallowUpstreamServiceLines(releaseCandidateBranch).FirstOrDefaultAsync(); var disposable = new CompositeDisposable(); var readyToFinalize = await CreateOrFastForwardServiceLine(releaseCandidateBranch, repository, cli); if (!readyToFinalize) { await AppendMessage($"{serviceLineBranch} unable to be fast-forwarded from {releaseCandidateBranch}; aborting", isError : true); } else { if (!string.IsNullOrEmpty(tagName)) { await AppendProcess(cli.AnnotatedTag(tagName, $"Automated release to service line {serviceLineBranch} from {releaseCandidateBranch}")).WaitUntilComplete(); } var serviceLine = await settings.GetBranchBasicDetails(serviceLineBranch).FirstOrDefaultAsync(); // possible TODO for the future: give option to add missing upstream lines always if (serviceLine == null) { // We need to set it up as a service line using (var work = unitOfWorkFactory.CreateUnitOfWork()) { settings.UpdateBranchSetting(serviceLineBranch, UpstreamMergePolicy.None, BranchGroupType.ServiceLine, work); foreach (var upstreamServiceLine in upstreamLines) { settings.AddBranchPropagation(upstreamServiceLine, serviceLineBranch, work); } await work.CommitAsync(); } } if (autoConsolidate) { var consolidating = (await repository.GetBranchDetails(releaseCandidateBranch).FirstOrDefaultAsync()).UpstreamBranchGroups; foreach (var upstreamServiceLine in upstreamLines) { var upstreamDetails = await repository.GetBranchDetails(upstreamServiceLine).FirstOrDefaultAsync(); consolidating = consolidating.Except(upstreamDetails.UpstreamBranchGroups).Except(new[] { upstreamServiceLine }).ToImmutableList(); } var releasedCandidate = await settings.GetConfiguredBranches().Select(branches => branches.Find(branch => branchIteration.IsBranchIteration(branch.GroupName, releaseCandidateBranch)).GroupName).FirstOrDefaultAsync(); #pragma warning disable CS4014 orchestration.EnqueueAction(new ConsolidateMergedAction(releasedCandidate, serviceLineBranch)); #pragma warning restore } if (!string.IsNullOrEmpty(tagName)) { await AppendProcess(cli.Push(tagName)).WaitUntilComplete(); } await AppendProcess(cli.Push(serviceLineBranch)).WaitUntilComplete(); } }