Hirthanan Subenderan | b186655 | 2020-03-20 14:01:14 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # -*- coding: utf-8 -*-" |
| 3 | # |
| 4 | # Copyright 2020 The Chromium OS Authors. All rights reserved. |
| 5 | # Use of this source code is governed by a BSD-style license that can be |
| 6 | # found in the LICENSE file. |
| 7 | |
| 8 | """Module containing methods interfacing with git |
| 9 | |
| 10 | i.e Parsing git logs for change-id, full commit sha's, etc. |
| 11 | """ |
| 12 | |
| 13 | from __future__ import print_function |
| 14 | import os |
| 15 | import re |
| 16 | import subprocess |
| 17 | import common |
| 18 | |
| 19 | |
| 20 | def get_upstream_fullsha(abbrev_sha): |
| 21 | """Returns the full upstream sha for an abbreviated 12 digit sha using git cli""" |
| 22 | upstream_absolute_path = common.get_kernel_absolute_path(common.UPSTREAM_PATH) |
| 23 | try: |
| 24 | cmd = ['git', '-C', upstream_absolute_path, 'rev-parse', abbrev_sha] |
| 25 | full_sha = subprocess.check_output(cmd).decode('utf-8') |
| 26 | return full_sha.rstrip() |
| 27 | except subprocess.CalledProcessError as e: |
| 28 | raise type(e)('Could not find full upstream sha for %s' % abbrev_sha, e.cmd) from e |
| 29 | |
| 30 | |
Hirthanan Subenderan | d6922c3 | 2020-03-23 14:17:40 -0700 | [diff] [blame^] | 31 | def get_commit_message(kernel_path, sha): |
| 32 | """Returns the commit message for a sha in a given local path to kernel.""" |
Hirthanan Subenderan | b186655 | 2020-03-20 14:01:14 -0700 | [diff] [blame] | 33 | try: |
Hirthanan Subenderan | d6922c3 | 2020-03-23 14:17:40 -0700 | [diff] [blame^] | 34 | cmd = ['git', '-C', kernel_path, 'log', |
| 35 | '--format=%B', '-n', '1', sha] |
Hirthanan Subenderan | b186655 | 2020-03-20 14:01:14 -0700 | [diff] [blame] | 36 | commit_message = subprocess.check_output(cmd).decode('utf-8', errors='ignore') |
| 37 | return commit_message |
| 38 | except subprocess.CalledProcessError as e: |
Hirthanan Subenderan | d6922c3 | 2020-03-23 14:17:40 -0700 | [diff] [blame^] | 39 | raise type(e)('Couldnt retrieve commit in kernel path %s for sha %s' |
| 40 | % (kernel_path, sha), e.cmd) from e |
| 41 | |
| 42 | |
| 43 | def get_upstream_commit_message(upstream_sha): |
| 44 | """Returns the commit message for a given upstream sha using git cli.""" |
| 45 | upstream_absolute_path = common.get_kernel_absolute_path(common.UPSTREAM_PATH) |
| 46 | return get_commit_message(upstream_absolute_path, upstream_sha) |
| 47 | |
| 48 | |
| 49 | def get_chrome_commit_message(chrome_sha): |
| 50 | """Returns the commit message for a given chrome sha using git cli.""" |
| 51 | chrome_absolute_path = common.get_kernel_absolute_path(common.CHROMEOS_PATH) |
| 52 | return get_commit_message(chrome_absolute_path, chrome_sha) |
Hirthanan Subenderan | b186655 | 2020-03-20 14:01:14 -0700 | [diff] [blame] | 53 | |
| 54 | |
| 55 | def get_commit_changeid_linux_chrome(kernel_sha): |
Hirthanan Subenderan | d6922c3 | 2020-03-23 14:17:40 -0700 | [diff] [blame^] | 56 | """Returns the changeid of the kernel_sha commit by parsing linux_chrome git log. |
| 57 | |
| 58 | kernel_sha will be one of linux_stable or linux_chrome commits. |
| 59 | """ |
Hirthanan Subenderan | b186655 | 2020-03-20 14:01:14 -0700 | [diff] [blame] | 60 | chrome_absolute_path = common.get_kernel_absolute_path(common.CHROMEOS_PATH) |
| 61 | try: |
| 62 | cmd = ['git', '-C', chrome_absolute_path, 'log', '--format=%B', '-n', '1', kernel_sha] |
| 63 | commit_message = subprocess.check_output(cmd).decode('utf-8', errors='ignore') |
| 64 | |
| 65 | m = re.findall('^Change-Id: (I[a-z0-9]{40})$', commit_message, re.M) |
| 66 | |
| 67 | # Get last change-id in case chrome sha cherry-picked/reverted into new commit |
| 68 | return m[-1] |
| 69 | except subprocess.CalledProcessError as e: |
Hirthanan Subenderan | d6922c3 | 2020-03-23 14:17:40 -0700 | [diff] [blame^] | 70 | raise type(e)('Couldnt retrieve changeid for commit %s' % kernel_sha, e.cmd) from e |
Hirthanan Subenderan | b186655 | 2020-03-20 14:01:14 -0700 | [diff] [blame] | 71 | except IndexError as e: |
Hirthanan Subenderan | d6922c3 | 2020-03-23 14:17:40 -0700 | [diff] [blame^] | 72 | # linux_stable kernel_sha's do not have an associated ChangeID |
| 73 | return None |
Hirthanan Subenderan | b186655 | 2020-03-20 14:01:14 -0700 | [diff] [blame] | 74 | |
| 75 | |
| 76 | def get_last_commit_sha_linux_chrome(): |
| 77 | """Retrieves the last SHA in linux_chrome repository.""" |
| 78 | chrome_absolute_path = common.get_kernel_absolute_path(common.CHROMEOS_PATH) |
| 79 | try: |
| 80 | cmd = ['git', '-C', chrome_absolute_path, 'rev-parse', 'HEAD'] |
| 81 | last_commit = subprocess.check_output(cmd).decode('utf-8') |
| 82 | return last_commit.rstrip() |
| 83 | except subprocess.CalledProcessError as e: |
| 84 | raise type(e)('Couldnt retrieve most recent commit in linux_chrome', e.cmd) from e |
| 85 | |
| 86 | |
| 87 | def cherry_pick_and_push_fix(fixer_upstream_sha, chromeos_branch, fix_commit_message): |
| 88 | """Cherry picks upstream commit into chrome repo.""" |
| 89 | cwd = os.getcwd() |
| 90 | chrome_absolute_path = common.get_kernel_absolute_path(common.CHROMEOS_PATH) |
| 91 | |
| 92 | # reset linux_chrome repo to remove local changes |
| 93 | try: |
| 94 | os.chdir(chrome_absolute_path) |
| 95 | subprocess.run(['git', 'checkout', chromeos_branch]) |
| 96 | subprocess.run(['git', 'reset', '--hard', 'origin/%s' % chromeos_branch]) |
| 97 | subprocess.run(['git', 'cherry-pick', '-n', fixer_upstream_sha]) |
| 98 | subprocess.run(['git', 'commit', '-s', '-m', fix_commit_message]) |
| 99 | |
| 100 | # commit has been cherry-picked and committed locally, precommit hook |
| 101 | # in git repository adds changeid to the commit message |
| 102 | last_commit = get_last_commit_sha_linux_chrome() |
| 103 | fixer_changeid = get_commit_changeid_linux_chrome(last_commit) |
| 104 | |
| 105 | subprocess.run(['git', 'push', 'origin', |
| 106 | 'HEAD:refs/for/%s%%t=autogenerated' % chromeos_branch]) |
| 107 | subprocess.run(['git', 'reset', '--hard', 'origin/%s' % chromeos_branch]) |
| 108 | |
| 109 | return fixer_changeid |
| 110 | except subprocess.CalledProcessError as e: |
| 111 | raise ValueError('Failed to cherrypick and push upstream fix %s on branch %s' |
| 112 | % (fixer_upstream_sha, chromeos_branch)) from e |
| 113 | finally: |
| 114 | subprocess.run(['git', 'reset', '--hard', 'origin/%s' % chromeos_branch]) |
| 115 | os.chdir(cwd) |