static async commitSetClosestToMiddleOfAllCommits()

in resources/perf.webkit.org/public/v3/commit-set-range-bisector.js [5:63]


    static async commitSetClosestToMiddleOfAllCommits(commitSetsToSplit, availableCommitSets)
    {
        console.assert(commitSetsToSplit.length === 2);
        const [firstCommitSet, secondCommitSet] = commitSetsToSplit;
        if (firstCommitSet.containsRootOrPatchOrOwnedCommit() || secondCommitSet.containsRootOrPatchOrOwnedCommit())
            return null;

        if (!firstCommitSet.hasSameRepositories(secondCommitSet))
            return null;

        const repositoriesWithCommitTime = new Set;
        const commitRangeByRepository = new Map;
        const indexForAllTimelessCommitsWithOrderByRepository = new Map;
        const allCommitsWithCommitTime = [];
        const repositoriesWithoutOrdering = [];

        await Promise.all(firstCommitSet.topLevelRepositories().map(async (repository) => {
            const firstCommit = firstCommitSet.commitForRepository(repository);
            const secondCommit = secondCommitSet.commitForRepository(repository);

            if (!CommitLog.hasOrdering(firstCommit, secondCommit)) {
                repositoriesWithoutOrdering.push(repository);
                commitRangeByRepository.set((repository), (commit) => commit === firstCommit || commit === secondCommit);
                return;
            }

            const [startCommit, endCommit] = CommitLog.orderTwoCommits(firstCommit, secondCommit);
            const commitsExcludingStartCommit = startCommit === endCommit ? [] : await CommitLog.fetchBetweenRevisions(repository, startCommit.revision(), endCommit.revision());

            if (startCommit.hasCommitTime()) {
                allCommitsWithCommitTime.push(startCommit, ...commitsExcludingStartCommit);
                commitRangeByRepository.set(repository, (commit) =>
                    commit.hasCommitTime() && startCommit.time() <= commit.time() && commit.time() <= endCommit.time());
                repositoriesWithCommitTime.add(repository);
            } else {
                const indexByCommit = new Map;
                indexByCommit.set(startCommit, 0);
                commitsExcludingStartCommit.forEach((commit, index) => indexByCommit.set(commit, index + 1));
                indexForAllTimelessCommitsWithOrderByRepository.set(repository, indexByCommit);
                commitRangeByRepository.set(repository, (commit) =>
                    commit.hasCommitOrder() && startCommit.order() <= commit.order() && commit.order() <= endCommit.order());
            }
        }));

        if (!repositoriesWithCommitTime.size && !indexForAllTimelessCommitsWithOrderByRepository.size && !repositoriesWithoutOrdering.size)
            return null;

        const commitSetsInRange = this._findCommitSetsWithinRange(firstCommitSet, secondCommitSet, availableCommitSets, commitRangeByRepository);
        let sortedCommitSets = this._orderCommitSetsByTimeAndOrderThenDeduplicate(commitSetsInRange, repositoriesWithCommitTime, [...indexForAllTimelessCommitsWithOrderByRepository.keys()], repositoriesWithoutOrdering);
        if (!sortedCommitSets.length)
            return null;

        let remainingCommitSets = this._closestCommitSetsToBisectingCommitByTime(sortedCommitSets, repositoriesWithCommitTime, allCommitsWithCommitTime);
        remainingCommitSets = this._findCommitSetsClosestToMiddleOfCommitsWithOrder(remainingCommitSets, indexForAllTimelessCommitsWithOrderByRepository);

        if (!remainingCommitSets.length)
            return null;
        return remainingCommitSets[Math.floor(remainingCommitSets.length / 2)];
    }