Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[run]
source = regzbot
omit = regzbot/testing*.py

[report]
fail_under = 60
show_missing = true
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ __pycache__
*.pyc
*.pyo
*.swp
.coverage
228 changes: 21 additions & 207 deletions regzbot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,14 @@ def init(databasedir):

@staticmethod
def update(dbcursor=None):
if dbcursor is None:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)

if not RegzbotDbMeta.table_exists("RegzbotState", dbcursor):
RegzbotState.db_create(1, dbcursor)

@staticmethod
def table_exists(tablename, dbcursor=None):
if dbcursor is None:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)
dbresult = dbcursor.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name=(?)", (tablename,)
).fetchone()
Expand All @@ -113,8 +111,7 @@ def table_exists(tablename, dbcursor=None):

@staticmethod
def set_tableversion(tablename, version, dbcursor=None):
if dbcursor is None:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)
dbcursor.execute(
"""
INSERT INTO RegzbotMeta
Expand All @@ -135,8 +132,7 @@ def db_create(version, dbcursor):

@staticmethod
def get(attribute, dbcursor=None):
if dbcursor is None:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)
dbresult = dbcursor.execute(
"SELECT value FROM RegzbotState WHERE attribute=(?)", (attribute,)
).fetchone()
Expand All @@ -146,8 +142,7 @@ def get(attribute, dbcursor=None):

@staticmethod
def set(attribute, value, dbcursor=None):
if dbcursor is None:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)
dbcursor.execute(
"""
INSERT OR REPLACE INTO RegzbotState
Expand All @@ -173,8 +168,7 @@ def db_create(version, dbcursor):

@staticmethod
def add(msgid, gmtime, dbcursor=None):
if dbcursor is None:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)

dbcursor.execute(
"""INSERT INTO msgidrecord
Expand All @@ -186,8 +180,7 @@ def add(msgid, gmtime, dbcursor=None):

@staticmethod
def check_presence(msgid, gmtime=None, dbcursor=None):
if dbcursor is None:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)

dbresult = dbcursor.execute(
"SELECT * FROM msgidrecord WHERE msgid=(?)", (msgid,)
Expand Down Expand Up @@ -931,8 +924,7 @@ def add(regid, repsrcid, entry, gmtime, subject, authorname, authormail):
return dbcursor.lastrowid

def delete(self, dbcursor=None):
if not dbcursor:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)

# delete related activities
for activity in RegActivityEvent.getall_by_actimonid(self.actimonid):
Expand Down Expand Up @@ -1157,8 +1149,7 @@ def db_create(version, dbcursor):
)""")

def delete(self, dbcursor=None):
if not dbcursor:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)

# delete related activities
if self.repsrcid and ReportSource.get_by_id(self.repsrcid, dbcursor).ismail():
Expand Down Expand Up @@ -1453,8 +1444,7 @@ def get_by_regid(cls, regid):

@staticmethod
def remove(regid, dbcursor=None):
if dbcursor is None:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)
dbresult = dbcursor.execute(
"SELECT subject FROM regbackburner WHERE regid=(?)", (regid,)
).fetchone()
Expand Down Expand Up @@ -1502,8 +1492,7 @@ def db_create(version, dbcursor):
)""")

def delete(self, dbcursor=None):
if not dbcursor:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)

if self.repsrcid and ReportSource.get_by_id(self.repsrcid, dbcursor).ismail():
RecordProcessedMsgids.delete(self.entry)
Expand Down Expand Up @@ -1757,8 +1746,7 @@ def get_by_reg_n_reptrd(cls, regression, reptrd):
yield cls(*dbresult)

def delete(self, dbcursor=None):
if not dbcursor:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)

dbcursor.execute(
"""DELETE FROM reglinks
Expand Down Expand Up @@ -2092,8 +2080,7 @@ def _db_update_solved(self):
)

def delete(self, dbcursor=None):
if not dbcursor:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)

for activity in RegActivityEvent.get_all(self.regid, onlyonce=False):
activity.delete(dbcursor=dbcursor)
Expand Down Expand Up @@ -2151,8 +2138,7 @@ def get_all(cls, order="regid", only_unsolved=False):

@classmethod
def get_by_regid(cls, regid, dbcursor=None):
if not dbcursor:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)
dbresult = dbcursor.execute(
"SELECT %s FROM regressions WHERE regid=?" % RegressionBasic.DBCOLS, (regid,)
).fetchone()
Expand All @@ -2162,8 +2148,7 @@ def get_by_regid(cls, regid, dbcursor=None):

@classmethod
def get_by_entry(cls, entry, dbcursor=None):
if not dbcursor:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)

dbresult = dbcursor.execute(
"SELECT %s FROM regressions INNER JOIN actmonitor ON actmonitor.regid = regressions.regid WHERE actmonitor.entry=?"
Expand Down Expand Up @@ -2263,23 +2248,6 @@ def get_expected_by_subject(cls, subject):
if dbresult:
yield cls(*dbresult)

@classmethod
def get_by_link(cls, link):
tmpstring = link
if tmpstring.startswith("https://"):
tmpstring = tmpstring.removeprefix("https://")
elif tmpstring.startswith("http://"):
tmpstring = tmpstring.removeprefix("http://")

if tmpstring.startswith("lore.kernel.org/"):
_, _, tmpstring = tmpstring.split("/", maxsplit=2)
msgid, _, _ = tmpstring.partition("/")
for regression in cls.get_by_entry(urldecode(msgid)):
return regression
else:
logger.warning("RegressionBasic.get_by_link(%s): unsupported domain ", link)
return None

@classmethod
def get_by_url(cls, url):
try:
Expand Down Expand Up @@ -2402,93 +2370,6 @@ def introduced_update(self, tagload):
self.introduced,
)

def __create_dup(self, url, gmtime):
subject = self.subject
repsrc, entry = ReportSource.get_by_url(url)

# defaults that normally will be overridden
authorname = "Unknown"
authormail = None

# create regression
return self.__create_obsolete(
self.introduced,
self.gitbranchid,
repsrc.repsrcid,
entry,
gmtime,
subject,
authorname,
authormail,
)

def _dupof_direct(
self, regression_other, gmtime, msgid, msgsubject, authorname, repsrcid, *, history=True
):
if self.regid == regression_other.regid:
logger.warning(
'regression[%s, "%s"]: request to mark this a as duplicate of ourselves; aborting',
self.regid,
self.subject,
)
# FIXME properly
sys.exit(1)

if self.solved_subject is None:
self.solved_subject = regression_other.subject

self.solved_gmtime = gmtime
self.solved_duplicateof = regression_other.regid

self._db_update_solved()

logger.info(
'regression[%s, "%s"]: marked as duplicate of regression Regression[%s, "%s"])',
self.regid,
self.subject,
regression_other.regid,
regression_other.subject,
)
if history:
# make sure this is mentioned in the other regression, too
RegHistory.event(
regression_other.regid,
gmtime,
msgid,
self.solved_subject,
authorname,
repsrcid=repsrcid,
regzbotcmd='dup: the regression "%s" was marked as duplicate of this'
% (self.subject),
)

def dupof(self, tagload, gmtime, msgid, msgsubject, authorname, repsrcid):
def parse(tagload):
tagload = tagload.split(maxsplit=1)
url = tagload[0]
if len(tagload) > 1:
subject = tagload[1]
else:
subject = None
return url, subject

urldup, self.solved_subject = parse(tagload)

regression_other = self.get_by_link(urldup)
if not regression_other:
regression_other = self.__create_dup(urldup, gmtime)
RegHistory.event(
regression_other.regid,
gmtime,
msgid,
msgsubject,
authorname,
repsrcid=repsrcid,
regzbotcmd="introduced: %s [implicit, due to usage of 'dup-of']" % self.introduced,
)

self._dupof_direct(regression_other, gmtime, msgid, msgsubject, authorname, repsrcid)

def fixed(self, gmtime, commit_hexsha, commit_subject, gitbranchid):
if self.solved_reason == "fixed":
logger.info(
Expand Down Expand Up @@ -2667,36 +2548,6 @@ def _solve_reason(self, reason, tagload, gmtime, msgid, repsrcid):
self.solved_repentry = msgid
self._db_update_solved()

def update_author(self, entry, tagload):
from email.utils import parseaddr

author, authormail = parseaddr(tagload)

dbcursor = DBCON.cursor()
dbcursor.execute(
"""UPDATE actmonitor
SET authorname = (?), authormail = (?)
WHERE regid=(?) and entry=(?)""",
(author, authormail, self.regid, entry),
)
logger.debug(
'[db regressions] author is now %s, authormail now %s (regid:%s; subject:"%s")',
author,
authormail,
self.regid,
self.subject,
)
logger.info(
'regression[%s, "%s"]: author is now %s, authormail now %s',
self.regid,
self.subject,
author,
authormail,
)

self.author = author
self.author = authormail

def title(self, tagload):
dbcursor = DBCON.cursor()
dbcursor.execute(
Expand Down Expand Up @@ -3225,8 +3076,7 @@ def modify(
)

def delete(self, dbcursor=None):
if not dbcursor:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)
dbresult = dbcursor.execute(
"""DELETE FROM reportsources
WHERE repsrcid=(?)""",
Expand Down Expand Up @@ -3255,8 +3105,7 @@ def islore(cls, repsrcid):

@classmethod
def get_by_id(cls, repsrcid, dbcursor=None):
if not dbcursor:
dbcursor = DBCON.cursor()
dbcursor = db_ensure_cursor(dbcursor)

dbresult = dbcursor.execute(
"SELECT * FROM reportsources WHERE repsrcid=(?)", (repsrcid,)
Expand Down Expand Up @@ -3525,6 +3374,10 @@ class RepDownloadError(Exception):
pass


def db_ensure_cursor(dbcursor=None):
return DBCON.cursor() if dbcursor is None else dbcursor


def db_close():
global DBCON
DBCON.close()
Expand Down Expand Up @@ -3641,45 +3494,6 @@ def timendate_gmtime_to_dt(gmtime):
return datetime.datetime.fromtimestamp(gmtime, tz=datetime.timezone.utc)


def parse_link(url):
tmpstring = url

if tmpstring.startswith("https://"):
tmpstring = tmpstring.removeprefix("https://")
elif tmpstring.startswith("http://"):
tmpstring = tmpstring.removeprefix("http://")

domain = mlist = msgid = None
if tmpstring.startswith("lore.kernel.org") or tmpstring.startswith("lkml.kernel.org"):
domain = "lore.kernel.org"
tmplist = tmpstring.split("/", maxsplit=2)
if len(tmplist) <= 2:
logger.debug("Ignoring %s, failed to parse", url)
return None, None, None

mlist = tmplist[1]
tmpstring = tmplist[2]

msgid, _, _ = tmpstring.partition("/")

if mlist == "r":
if tmpstring.startswith("lkml.kernel.org"):
mlist = "lkml"
else:
# FIXMELATER: this is the lore redirector; for now just assume it redirecting to LKML, which likely needs fixing later
mlist = "lkml"
elif tmpstring.startswith("bugzilla.kernel.org"):
bugid = tmpstring.removeprefix("bugzilla.kernel.org/show_bug.cgi?id=")
if bugid.isnumeric():
msgid = bugid
domain = "bugzilla.kernel.org"
else:
logger.debug("Tried to get bugid from %s, but failed", url)
else:
logger.debug("Tried to get msgid from %s, but don't known how to handle that domain", url)
return domain, mlist, msgid


def basicressource_checkdir_exists(directory, create=False):
try:
if os.path.exists(directory):
Expand Down
Loading
Loading