예제 #1
0
    def get_next(self):
        """Computes the next commit to test.

        This takes skip-ranges into account and prioritizes finding the first
        commit that unbreaks a skip range.

        May add commits for cherry pick. Returns `False` when the bisect is
        finished.
        """
        patchset = read_patchset()
        considered_good = get_good_commits() + get_skip_range_commits(patchset)
        candidates = git.get_bisect_all(considered_good, "refs/bisect/bad")
        # It would be better to use a more sophisticated algorithm like
        # https://github.com/git/git/commit/ebc9529f0358bdb10192fa27bc75f5d4e452ce90
        # This works for now though.
        commit = first_not_skipped(candidates)
        if git.rev_parse(commit) == git.rev_parse("refs/bisect/bad"):
            skip_ranges = []
            good_commits = [git.rev_parse(ref) for ref in get_good_commits()]
            for parent in git.parents(commit):
                if parent in good_commits:
                    print(f"First bad found! Here it is: {commit}")
                    return None
                skip_ranges += skip_ranges_of_commit(parent, patchset)
            print(f"cherry-pick {commit} to unbreak {skip_ranges}")
            patchset.insert(0, commit)
            git.update_ref(f"refs/bisect/{patchset_identifier(patchset)}/head",
                           commit)
            return self.get_next()
        return commit
예제 #2
0
    def get_next(self):
        """Computes the next commit to test.

        This takes skip-ranges into account and prioritizes finding the first
        commit that unbreaks a skip range.

        May add commits for cherry pick. Returns `False` when the bisect is
        finished.
        """
        patchset = read_patchset()
        considered_good = get_good_commits() + get_skip_range_commits(patchset)
        commit = git.get_bisect_info(considered_good, "refs/bisect/bad")["bisect_rev"]
        if git.rev_parse(commit) == git.rev_parse("refs/bisect/bad"):
            skip_ranges = []
            good_commits = [git.rev_parse(ref) for ref in get_good_commits()]
            for parent in git.parents(commit):
                if parent in good_commits:
                    print(f"First bad found! Here it is: {commit}")
                    return None
                skip_ranges += skip_ranges_of_commit(parent, patchset)
            print(f"cherry-pick {commit} to unbreak {skip_ranges}")
            patchset.insert(0, commit)
            git.update_ref(f"refs/bisect/{patchset_identifier(patchset)}/head", commit)
            return self.get_next()
        return commit
예제 #3
0
def bisect_good(commit):
    """Mark a commit as good.

    The same disclaimer as for `bisect_bad` applies.
    """
    # alternative: `git bisect--helper bisect-write`
    rev_parsed = git.rev_parse(commit)
    git.update_ref(f"refs/bisect/good-{rev_parsed}", commit)
    bisect_append_log(f"# good: {git.rev_pretty(commit)}")
    bisect_append_log(f"git bisect good {git.rev_parse(commit)}")
예제 #4
0
def bisect_skip(commit):
    """Mark a single commit as skipped.

    This is the traditional `git bisect skip`. The commits skipped with this do
    not mark a range, and the algorithm will not attempt to "unbreak" the
    commits.
    """
    rev_parsed = git.rev_parse(commit)
    git.update_ref(f"refs/bisect/skip-{rev_parsed}", commit)
    bisect_append_log(f"# skip: {git.rev_pretty(commit)}")
    bisect_append_log(f"git bisect skip {git.rev_parse(commit)}")
예제 #5
0
def named_skip(name, patchset, commit):
    """Mark a commit as belonging to a named skip range.

    In contrast to a regular `git bisect skip`, all commits between two commits
    in the range are considered skipped as well.
    """
    unique_name = git.rev_parse(commit)
    git.update_ref(
        f"refs/bisect/break/{patchset_identifier(patchset)}/markers/{name}/{unique_name}",
        commit,
    )
예제 #6
0
def has_good_and_bad():
    """Determines if the bisect can start"""
    return len(get_good_commits()) > 0 and git.rev_parse(
        "refs/bisect/bad") is not None