From: Simon Glass <simon.glass@canonical.com> Move the merge-walking loop into its own function to reduce the complexity of get_next_commits() Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- tools/pickman/control.py | 91 ++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 36 deletions(-) diff --git a/tools/pickman/control.py b/tools/pickman/control.py index cd138612623..0418fbe2da6 100644 --- a/tools/pickman/control.py +++ b/tools/pickman/control.py @@ -745,6 +745,59 @@ def do_check_gitlab(args, dbs): # pylint: disable=unused-argument return 0 +def find_unprocessed_commits(dbs, last_commit, source, merge_hashes): + """Find the first merge with unprocessed commits + + Walks through the merge hashes in order, looking for one that has + commits not yet tracked in the database. + + Args: + dbs (Database): Database instance + last_commit (str): Hash of the last cherry-picked commit + source (str): Source branch name + merge_hashes (list): List of merge commit hashes to check + + Returns: + NextCommitsInfo: Info about the next commits to process + """ + prev_commit = last_commit + for merge_hash in merge_hashes: + # Get all commits from prev_commit to this merge + log_output = run_git([ + 'log', '--reverse', '--format=%H|%h|%an|%s|%P', + f'{prev_commit}..{merge_hash}' + ]) + + if not log_output: + prev_commit = merge_hash + continue + + # Parse commits, filtering out those already in database + all_commits = parse_log_output(log_output, has_parents=True) + commits = [c for c in all_commits + if not dbs.commit_get(c.hash)] + + if commits: + return NextCommitsInfo(commits, True) + + # All commits in this merge are processed, skip to next + prev_commit = merge_hash + + # No merges with unprocessed commits, check remaining commits + log_output = run_git([ + 'log', '--reverse', '--format=%H|%h|%an|%s|%P', + f'{prev_commit}..{source}' + ]) + + if not log_output: + return NextCommitsInfo([], False) + + all_commits = parse_log_output(log_output, has_parents=True) + commits = [c for c in all_commits if not dbs.commit_get(c.hash)] + + return NextCommitsInfo(commits, False) + + def get_next_commits(dbs, source): """Get the next set of commits to cherry-pick from a source @@ -786,42 +839,8 @@ def get_next_commits(dbs, source): if len(parents) > 1: merge_hashes.append(parts[0]) - # Try each merge in order until we find one with unprocessed commits - prev_commit = last_commit - for merge_hash in merge_hashes: - # Get all commits from prev_commit to this merge - log_output = run_git([ - 'log', '--reverse', '--format=%H|%h|%an|%s|%P', - f'{prev_commit}..{merge_hash}' - ]) - - if not log_output: - prev_commit = merge_hash - continue - - # Parse commits, filtering out those already in database - all_commits = parse_log_output(log_output, has_parents=True) - commits = [c for c in all_commits if not dbs.commit_get(c.hash)] - - if commits: - return NextCommitsInfo(commits, True), None - - # All commits in this merge are processed, skip to next - prev_commit = merge_hash - - # No merges with unprocessed commits, check remaining commits - log_output = run_git([ - 'log', '--reverse', '--format=%H|%h|%an|%s|%P', - f'{prev_commit}..{source}' - ]) - - if not log_output: - return NextCommitsInfo([], False), None - - all_commits = parse_log_output(log_output, has_parents=True) - commits = [c for c in all_commits if not dbs.commit_get(c.hash)] - - return NextCommitsInfo(commits, False), None + return find_unprocessed_commits( + dbs, last_commit, source, merge_hashes), None def get_commits_for_pick(commit_spec): -- 2.43.0