| #!/usr/bin/env python3 |
| # -*- coding: utf-8 -*-" |
| # |
| # Copyright 2020 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Find missing stable and backported mainline fix patches in chromeos.""" |
| |
| from __future__ import print_function |
| |
| import MySQLdb |
| |
| import common |
| |
| DEFAULT_MERGED_REASON = 'Fix merged into linux chrome' |
| |
| def get_fixes_table_primary_key(db, fixes_table, fix_change_id): |
| """Retrieves the primary keys from a fixes table using changeid.""" |
| c = db.cursor(MySQLdb.cursors.DictCursor) |
| |
| q = """SELECT kernel_sha, fixedby_upstream_sha |
| FROM {fixes_table} |
| WHERE fix_change_id = %s""".format(fixes_table=fixes_table) |
| |
| c.execute(q, [fix_change_id]) |
| row = c.fetchone() |
| return (row['kernel_sha'], row['fixedby_upstream_sha']) |
| |
| |
| def get_fix_status_and_changeid(db, fixes_table, kernel_sha, fixedby_upstream_sha): |
| """Get branch, fix_change_id, initial_status and status for a unique row in fixes table.""" |
| c = db.cursor(MySQLdb.cursors.DictCursor) |
| |
| q = """SELECT branch, fix_change_id, initial_status, status |
| FROM {fixes_table} |
| WHERE kernel_sha = %s |
| AND fixedby_upstream_sha = %s""".format(fixes_table=fixes_table) |
| |
| c.execute(q, [kernel_sha, fixedby_upstream_sha]) |
| row = c.fetchone() |
| return row |
| |
| |
| def update_change_abandoned(db, fixes_table, kernel_sha, fixedby_upstream_sha, reason=None): |
| """Updates fixes_table unique fix row to indicate fix cl has been abandoned. |
| |
| Function will only abandon rows in the table which have status OPEN or CONFLICT. |
| """ |
| c = db.cursor() |
| q = """UPDATE {fixes_table} |
| SET status = 'ABANDONED', close_time = %s, reason = %s |
| WHERE kernel_sha = %s |
| AND fixedby_upstream_sha = %s |
| AND (status = 'OPEN' OR status = 'CONFLICT')""".format(fixes_table=fixes_table) |
| close_time = common.get_current_time() |
| c.execute(q, [close_time, reason, kernel_sha, fixedby_upstream_sha]) |
| db.commit() |
| |
| |
| def update_change_restored(db, fixes_table, kernel_sha, fixedby_upstream_sha, reason=None): |
| """Updates fixes_table unique fix row to indicate fix cl has been reopened.""" |
| row = get_fix_status_and_changeid(db, fixes_table, kernel_sha, fixedby_upstream_sha) |
| status = 'OPEN' if row['fix_change_id'] else row['initial_status'] |
| |
| c = db.cursor() |
| q = """UPDATE {fixes_table} |
| SET status = %s, close_time = %s, reason = %s |
| WHERE kernel_sha = %s |
| AND fixedby_upstream_sha = %s |
| AND status = 'ABANDONED'""".format(fixes_table=fixes_table) |
| close_time = None |
| c.execute(q, [status, close_time, reason, kernel_sha, fixedby_upstream_sha]) |
| db.commit() |
| |
| |
| def update_change_merged(db, fixes_table, kernel_sha, fixedby_upstream_sha, |
| reason=DEFAULT_MERGED_REASON): |
| """Updates fixes_table unique fix row to indicate fix cl has been merged.""" |
| c = db.cursor() |
| q = """UPDATE {fixes_table} |
| SET status = 'MERGED', close_time = %s, reason = %s |
| WHERE kernel_sha = %s |
| AND fixedby_upstream_sha = %s""".format(fixes_table=fixes_table) |
| close_time = common.get_current_time() |
| c.execute(q, [close_time, reason, kernel_sha, fixedby_upstream_sha]) |
| db.commit() |
| |
| |
| def update_change_status(db, fixes_table, fix_change_id, status): |
| """Updates fixes_table with the latest status from Gerrit API. |
| |
| This is done to synchronize CL's that are |
| abandoned/restored on Gerrit with our database state |
| """ |
| kernel_sha, fixedby_upstream_sha = get_fixes_table_primary_key(db, fixes_table, fix_change_id) |
| if status == common.Status.OPEN: |
| update_change_restored(db, fixes_table, kernel_sha, fixedby_upstream_sha) |
| elif status == common.Status.ABANDONED: |
| update_change_abandoned(db, fixes_table, kernel_sha, fixedby_upstream_sha) |
| elif status == common.Status.MERGED: |
| update_change_merged(db, fixes_table, kernel_sha, fixedby_upstream_sha) |
| else: |
| raise ValueError('Change should be either OPEN, ABANDONED, or MERGED') |
| |
| |
| def update_conflict_to_open(db, fixes_table, kernel_sha, fixedby_upstream_sha, fix_change_id): |
| """Updates fixes_table to represent an open change that previously resulted in conflict.""" |
| c = db.cursor() |
| reason = 'Patch applies cleanly after originally conflicting.' |
| q = """UPDATE {fixes_table} |
| SET status = 'OPEN', fix_change_id = %s, reason = %s |
| WHERE kernel_sha = %s |
| AND fixedby_upstream_sha = %s""".format(fixes_table=fixes_table) |
| c.execute(q, [fix_change_id, reason, kernel_sha, fixedby_upstream_sha]) |
| db.commit() |