in libmozdata/patchanalysis.py [0:0]
def bug_analysis(bug, uplift_channel=None, author_cache={}, reviewer_cache={}):
if isinstance(bug, numbers.Number):
bug_id = bug
bug = {}
def bughandler(found_bug):
bug.update(found_bug)
def commenthandler(found_bug, bugid):
bug["comments"] = found_bug["comments"]
def attachmenthandler(attachments, bugid):
bug["attachments"] = attachments
def historyhandler(found_bug):
bug["history"] = found_bug["history"]
INCLUDE_FIELDS = [
"id",
"flags",
"depends_on",
"keywords",
"blocks",
"whiteboard",
"resolution",
"status",
"url",
"version",
"summary",
"priority",
"product",
"component",
"severity",
"platform",
"op_sys",
"cc",
"assigned_to",
"creator",
]
ATTACHMENT_INCLUDE_FIELDS = ["flags", "is_patch", "creator", "content_type"]
COMMENT_INCLUDE_FIELDS = ["id", "text", "author", "time"]
Bugzilla(
bug_id,
INCLUDE_FIELDS,
bughandler=bughandler,
commenthandler=commenthandler,
comment_include_fields=COMMENT_INCLUDE_FIELDS,
attachmenthandler=attachmenthandler,
historyhandler=historyhandler,
attachment_include_fields=ATTACHMENT_INCLUDE_FIELDS,
).get_data().wait()
info = {
"backout_num": 0,
"blocks": len(bug["blocks"]),
"depends_on": len(bug["depends_on"]),
"comments": len(bug["comments"]),
"r-ed_patches": sum(
(a["is_patch"] == 1 or a["content_type"] == "text/x-review-board-request")
and sum(
flag["name"] == "review" and flag["status"] == "-"
for flag in a["flags"]
)
> 0
for a in bug["attachments"]
),
"patches": {},
}
# Store in-testsuite flag.
in_testsuite = [
flag["status"] for flag in bug["flags"] if flag["name"] == "in-testsuite"
]
info["in-testsuite"] = in_testsuite[0] if len(in_testsuite) > 0 else ""
# Store bug creator & assignee
assignee = bug.get("assigned_to_detail")
creator = bug.get("creator_detail")
# Get all reviewers and authors, we will match them with the changeset description (r=XXX).
bugzilla_authors, bugzilla_reviewers = get_bugzilla_authors_reviewers(bug)
revs, backout_comments = get_commits_for_bug(bug)
if len(revs) > 0:
for rev, obj in revs.items():
# Multiple names because sometimes authors use different emails on Bugzilla and Mercurial and sometimes
# they change it.
author_names = author_match(
obj["author_mercurial"],
obj["author_real_name"],
bugzilla_authors,
bug["cc_detail"],
author_cache,
)
reviewers = set()
short_reviewers = obj["reviewers"]
for short_reviewer in short_reviewers:
# This changeset was not reviewed (probably a simple fix).
if short_reviewer not in ["me", "oops", "none", "bustage", "backout"]:
reviewers.add(
reviewer_match(
short_reviewer,
bugzilla_reviewers | bugzilla_authors,
bug["cc_detail"],
reviewer_cache,
)
)
# Human readable patch URL
info["patches"][rev] = {
"source": "mercurial",
"url": hgmozilla.Mercurial.get_repo_url(obj["channel"])
+ "/rev/{}".format(rev),
}
info["patches"][rev].update(
patch_analysis(
hgmozilla.RawRevision.get_revision(obj["channel"], rev),
author_names,
reviewers,
utils.as_utc(datetime.utcfromtimestamp(obj["creation_date"])),
)
)
else:
def attachmenthandler(attachments, bugid):
for i in range(0, len(bug["attachments"])):
bug["attachments"][i].update(attachments[i])
Bugzilla(
bug["id"],
attachmenthandler=attachmenthandler,
attachment_include_fields=["id", "data", "is_obsolete", "creation_time"],
).get_data().wait()
for attachment in bug["attachments"]:
if (
sum(
flag["name"] == "review" and flag["status"] == "+"
for flag in attachment["flags"]
)
== 0
):
continue
data = None
if attachment["is_patch"] == 1 and attachment["is_obsolete"] == 0:
info["patches"][attachment["id"]] = {
"source": "attachment",
"url": "{}/attachment.cgi?id={}".format(
Bugzilla.URL, attachment["id"]
),
}
data = base64.b64decode(attachment["data"]).decode("ascii", "ignore")
elif (
attachment["content_type"] == "text/x-review-board-request"
and attachment["is_obsolete"] == 0
):
mozreview_url = base64.b64decode(attachment["data"]).decode("utf-8")
info["patches"][attachment["id"]] = {
"source": "mozreview",
"url": mozreview_url,
}
review_num = re.search(MOZREVIEW_URL_PATTERN, mozreview_url).group(1)
mozreview_raw_diff_url = (
"https://reviewboard.mozilla.org/r/" + review_num + "/diff/raw/"
)
response = urlopen(mozreview_raw_diff_url)
data = response.read().decode("ascii", "ignore")
if data is not None:
info["patches"][attachment["id"]].update(
patch_analysis(
data,
[attachment["creator"]],
bugzilla_reviewers,
utils.get_date_ymd(attachment["creation_time"]),
)
)
# TODO: Add number of crashes with signatures from the bug (also before/after the patch?).
# TODO: Add perfherder results?
info["backout_num"] = len(backout_comments)
# Add users
info["users"] = {
"creator": creator,
"assignee": assignee,
"authors": bugzilla_authors,
"reviewers": bugzilla_reviewers,
}
if uplift_channel is not None:
# Add uplift request
info.update(uplift_info(bug, uplift_channel))
return info