blob: f8ccef2dc2d8529a22432f3ed1860b52a67be878 [file] [log] [blame]
Hirthanan Subenderan3e884d62020-01-23 13:12:45 -08001#!/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 parses and stores mainline linux patches to be easily accessible."""
9
10from __future__ import print_function
11
12import os
13import re
14import sqlite3
15import subprocess
16from config import UPSTREAM_PATH, STABLE_BRANCHES
17from common import WORKDIR, UPSTREAMDB, createdb
18
19
20UPSTREAM_BASE = 'v' + STABLE_BRANCHES[0]
21
22RF = re.compile(r'^\s*Fixes: (?:commit )*([0-9a-f]+).*')
23RDESC = re.compile(r'.* \("([^"]+)"\).*')
24
25
26def make_tables(c):
27 """Initializes the upstreamdb tables."""
28 # Upstream commits
29 c.execute('CREATE TABLE commits (sha text, description text)')
30 c.execute('CREATE UNIQUE INDEX commit_sha ON commits (sha)')
31
32 # Fixes associated with upstream commits. sha is the commit, fsha is its fix.
33 # Each sha may have multiple fixes associated with it.
34 c.execute('CREATE TABLE fixes \
35 (sha text, fsha text, patchid text, ignore integer)')
36 c.execute('CREATE INDEX sha ON fixes (sha)')
37
38
39def handle(start):
40 """Parses git logs and builds upstreamdb tables."""
41 conn = sqlite3.connect(UPSTREAMDB)
42 conn.text_factory = str
43 c = conn.cursor()
44 c2 = conn.cursor()
45
46 commits = subprocess.check_output(['git', 'log', '--abbrev=12', '--oneline',
47 '--no-merges', '--reverse', start+'..'])
48 for commit in commits.decode('utf-8').splitlines():
49 if commit != '':
50 elem = commit.split(' ', 1)
51 sha = elem[0]
52 last = sha
53
54 # skip if SHA is already in database. This will happen
55 # for the first SHA when the script is re-run.
56 c.execute("select sha from commits where sha is '%s'" % sha)
57 if c.fetchone():
58 continue
59
60 description = elem[1].rstrip('\n')
61 c.execute('INSERT INTO commits(sha, description) VALUES (?, ?)',
62 (sha, description))
63 # check if this patch fixes a previous patch.
64 subprocess_cmd = ['git', 'show', '-s', '--pretty=format:%b', sha]
65 description = subprocess.check_output(subprocess_cmd).decode('utf-8')
66 for d in description.splitlines():
67 m = RF.search(d)
68 fsha = None
69 if m and m.group(1):
70 try:
71 # Normalize fsha to 12 characters
72 cmd = 'git show -s --pretty=format:%%H %s' % m.group(1)
73 fsha = subprocess.check_output(cmd.split(' '),
74 stderr=subprocess.DEVNULL).decode('utf-8')
75 except subprocess.CalledProcessError:
76 print("Commit '%s' for SHA '%s': "
77 'Not found' % (m.group(0), sha))
78 m = RDESC.search(d)
79 if m:
80 desc = m.group(1)
81 desc = desc.replace("'", "''")
82 c2.execute('select sha from commits where '
83 "description is '%s'" % desc)
84 fsha = c2.fetchone()
85 if fsha:
86 fsha = fsha[0]
87 print(" Real SHA may be '%s'" % fsha)
88 # The Fixes: tag may be wrong. The sha may not be in the
89 # upstream kernel, or the format may be completely wrong
90 # and m.group(1) may not be a sha in the first place.
91 # In that case, do nothing.
92 if fsha:
93 print('Commit %s fixed by %s' % (fsha[0:12], sha))
94 # Calculate patch ID for fixing commit.
95 ps = subprocess.Popen(['git', 'show', sha],
96 stdout=subprocess.PIPE)
97 spid = subprocess.check_output(['git', 'patch-id'],
98 stdin=ps.stdout).decode('utf-8', errors='ignore')
99 patchid = spid.split(' ', 1)[0]
100
101 # Insert in reverse order: sha is fixed by fsha.
102 # patchid is the patch ID associated with fsha (in the db).
103 c.execute('INSERT into fixes (sha, fsha, patchid, ignore) '
104 'VALUES (?, ?, ?, ?)',
105 (fsha[0:12], sha, patchid, 0))
106
107 if last:
108 c.execute("UPDATE tip set sha='%s' where ref=1" % last)
109
110 conn.commit()
111 conn.close()
112
113
114def update_upstreamdb():
115 """Updates the upstreamdb database."""
116 start = UPSTREAM_BASE
117
118 try:
119 # see if we previously handled anything. If yes, use it.
120 # Otherwise re-create database
121 conn = sqlite3.connect(UPSTREAMDB)
122 conn.text_factory = str
123 c = conn.cursor()
124 c.execute('select sha from tip')
125 sha = c.fetchone()
126 conn.close()
127 if sha and sha[0] != '':
128 start = sha[0]
129 except sqlite3.Error:
130 createdb(UPSTREAMDB, make_tables)
131
132 os.chdir(UPSTREAM_PATH)
133 subprocess.check_output(['git', 'pull'])
134
135 handle(start)
136
137 os.chdir(WORKDIR)
138
139
140if __name__ == '__main__':
141 update_upstreamdb()