[llvm] f4c18a4 - [Utils] Delete find_interesting_reviews.py script (#196347)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 7 08:20:28 PDT 2026
Author: Aiden Grossman
Date: 2026-05-07T08:20:23-07:00
New Revision: f4c18a4d0796ced3a73bd453c807f41538b979be
URL: https://github.com/llvm/llvm-project/commit/f4c18a4d0796ced3a73bd453c807f41538b979be
DIFF: https://github.com/llvm/llvm-project/commit/f4c18a4d0796ced3a73bd453c807f41538b979be.diff
LOG: [Utils] Delete find_interesting_reviews.py script (#196347)
This was phabricator specific which has not been around for a while now.
Added:
Modified:
Removed:
llvm/utils/Reviewing/find_interesting_reviews.py
################################################################################
diff --git a/llvm/utils/Reviewing/find_interesting_reviews.py b/llvm/utils/Reviewing/find_interesting_reviews.py
deleted file mode 100644
index c006691079b64..0000000000000
--- a/llvm/utils/Reviewing/find_interesting_reviews.py
+++ /dev/null
@@ -1,775 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import print_function
-
-import argparse
-import email.mime.multipart
-import email.mime.text
-import logging
-import os.path
-import pickle
-import re
-import smtplib
-import subprocess
-import sys
-from datetime import datetime, timedelta
-from phabricator import Phabricator
-
-# Setting up a virtualenv to run this script can be done by running the
-# following commands:
-# $ virtualenv venv
-# $ . ./venv/bin/activate
-# $ pip install Phabricator
-
-GIT_REPO_METADATA = (("llvm-monorepo", "https://github.com/llvm/llvm-project"),)
-
-# The below PhabXXX classes represent objects as modelled by Phabricator.
-# The classes can be serialized to disk, to try and make sure that we don't
-# needlessly have to re-fetch lots of data from Phabricator, as that would
-# make this script unusably slow.
-
-
-class PhabObject:
- OBJECT_KIND = None
-
- def __init__(self, id):
- self.id = id
-
-
-class PhabObjectCache:
- def __init__(self, PhabObjectClass):
- self.PhabObjectClass = PhabObjectClass
- self.most_recent_info = None
- self.oldest_info = None
- self.id2PhabObjects = {}
-
- def get_name(self):
- return self.PhabObjectClass.OBJECT_KIND + "sCache"
-
- def get(self, id):
- if id not in self.id2PhabObjects:
- self.id2PhabObjects[id] = self.PhabObjectClass(id)
- return self.id2PhabObjects[id]
-
- def get_ids_in_cache(self):
- return list(self.id2PhabObjects.keys())
-
- def get_objects(self):
- return list(self.id2PhabObjects.values())
-
- DEFAULT_DIRECTORY = "PhabObjectCache"
-
- def _get_pickle_name(self, directory):
- file_name = "Phab" + self.PhabObjectClass.OBJECT_KIND + "s.pickle"
- return os.path.join(directory, file_name)
-
- def populate_cache_from_disk(self, directory=DEFAULT_DIRECTORY):
- """
- FIXME: consider if serializing to JSON would bring interoperability
- advantages over serializing to pickle.
- """
- try:
- f = open(self._get_pickle_name(directory), "rb")
- except IOError as err:
- print("Could not find cache. Error message: {0}. Continuing...".format(err))
- else:
- with f:
- try:
- d = pickle.load(f)
- self.__dict__.update(d)
- except EOFError as err:
- print(
- "Cache seems to be corrupt. "
- + "Not using cache. Error message: {0}".format(err)
- )
-
- def write_cache_to_disk(self, directory=DEFAULT_DIRECTORY):
- if not os.path.exists(directory):
- os.makedirs(directory)
- with open(self._get_pickle_name(directory), "wb") as f:
- pickle.dump(self.__dict__, f)
- print(
- "wrote cache to disk, most_recent_info= {0}".format(
- datetime.fromtimestamp(self.most_recent_info)
- if self.most_recent_info is not None
- else None
- )
- )
-
-
-class PhabReview(PhabObject):
- OBJECT_KIND = "Review"
-
- def __init__(self, id):
- PhabObject.__init__(self, id)
-
- def update(self, title, dateCreated, dateModified, author):
- self.title = title
- self.dateCreated = dateCreated
- self.dateModified = dateModified
- self.author = author
-
- def setPhabDiffs(self, phabDiffs):
- self.phabDiffs = phabDiffs
-
-
-class PhabUser(PhabObject):
- OBJECT_KIND = "User"
-
- def __init__(self, id):
- PhabObject.__init__(self, id)
-
- def update(self, phid, realName):
- self.phid = phid
- self.realName = realName
-
-
-class PhabHunk:
- def __init__(self, rest_api_hunk):
- self.oldOffset = int(rest_api_hunk["oldOffset"])
- self.oldLength = int(rest_api_hunk["oldLength"])
- # self.actual_lines_changed_offset will contain the offsets of the
- # lines that were changed in this hunk.
- self.actual_lines_changed_offset = []
- offset = self.oldOffset
- inHunk = False
- hunkStart = -1
- contextLines = 3
- for line in rest_api_hunk["corpus"].split("\n"):
- if line.startswith("+"):
- # line is a new line that got introduced in this patch.
- # Do not record it as a changed line.
- if inHunk is False:
- inHunk = True
- hunkStart = max(self.oldOffset, offset - contextLines)
- continue
- if line.startswith("-"):
- # line was changed or removed from the older version of the
- # code. Record it as a changed line.
- if inHunk is False:
- inHunk = True
- hunkStart = max(self.oldOffset, offset - contextLines)
- offset += 1
- continue
- # line is a context line.
- if inHunk is True:
- inHunk = False
- hunkEnd = offset + contextLines
- self.actual_lines_changed_offset.append((hunkStart, hunkEnd))
- offset += 1
- if inHunk is True:
- hunkEnd = offset + contextLines
- self.actual_lines_changed_offset.append((hunkStart, hunkEnd))
-
- # The above algorithm could result in adjacent or overlapping ranges
- # being recorded into self.actual_lines_changed_offset.
- # Merge the adjacent and overlapping ranges in there:
- t = []
- lastRange = None
- for start, end in self.actual_lines_changed_offset + [
- (sys.maxsize, sys.maxsize)
- ]:
- if lastRange is None:
- lastRange = (start, end)
- else:
- if lastRange[1] >= start:
- lastRange = (lastRange[0], end)
- else:
- t.append(lastRange)
- lastRange = (start, end)
- self.actual_lines_changed_offset = t
-
-
-class PhabChange:
- def __init__(self, rest_api_change):
- self.oldPath = rest_api_change["oldPath"]
- self.hunks = [PhabHunk(h) for h in rest_api_change["hunks"]]
-
-
-class PhabDiff(PhabObject):
- OBJECT_KIND = "Diff"
-
- def __init__(self, id):
- PhabObject.__init__(self, id)
-
- def update(self, rest_api_results):
- self.revisionID = rest_api_results["revisionID"]
- self.dateModified = int(rest_api_results["dateModified"])
- self.dateCreated = int(rest_api_results["dateCreated"])
- self.changes = [PhabChange(c) for c in rest_api_results["changes"]]
-
-
-class ReviewsCache(PhabObjectCache):
- def __init__(self):
- PhabObjectCache.__init__(self, PhabReview)
-
-
-class UsersCache(PhabObjectCache):
- def __init__(self):
- PhabObjectCache.__init__(self, PhabUser)
-
-
-reviews_cache = ReviewsCache()
-users_cache = UsersCache()
-
-
-def init_phab_connection():
- phab = Phabricator()
- phab.update_interfaces()
- return phab
-
-
-def update_cached_info(
- phab,
- cache,
- phab_query,
- order,
- record_results,
- max_nr_entries_per_fetch,
- max_nr_days_to_cache,
-):
- q = phab
- LIMIT = max_nr_entries_per_fetch
- for query_step in phab_query:
- q = getattr(q, query_step)
- results = q(order=order, limit=LIMIT)
- most_recent_info, oldest_info = record_results(cache, results, phab)
- oldest_info_to_fetch = datetime.fromtimestamp(most_recent_info) - timedelta(
- days=max_nr_days_to_cache
- )
- most_recent_info_overall = most_recent_info
- cache.write_cache_to_disk()
- after = results["cursor"]["after"]
- print("after: {0!r}".format(after))
- print("most_recent_info: {0}".format(datetime.fromtimestamp(most_recent_info)))
- while (
- after is not None and datetime.fromtimestamp(oldest_info) > oldest_info_to_fetch
- ):
- need_more_older_data = (
- cache.oldest_info is None
- or datetime.fromtimestamp(cache.oldest_info) > oldest_info_to_fetch
- )
- print(
- (
- "need_more_older_data={0} cache.oldest_info={1} "
- + "oldest_info_to_fetch={2}"
- ).format(
- need_more_older_data,
- datetime.fromtimestamp(cache.oldest_info)
- if cache.oldest_info is not None
- else None,
- oldest_info_to_fetch,
- )
- )
- need_more_newer_data = (
- cache.most_recent_info is None or cache.most_recent_info < most_recent_info
- )
- print(
- (
- "need_more_newer_data={0} cache.most_recent_info={1} "
- + "most_recent_info={2}"
- ).format(need_more_newer_data, cache.most_recent_info, most_recent_info)
- )
- if not need_more_older_data and not need_more_newer_data:
- break
- results = q(order=order, after=after, limit=LIMIT)
- most_recent_info, oldest_info = record_results(cache, results, phab)
- after = results["cursor"]["after"]
- print("after: {0!r}".format(after))
- print("most_recent_info: {0}".format(datetime.fromtimestamp(most_recent_info)))
- cache.write_cache_to_disk()
- cache.most_recent_info = most_recent_info_overall
- if after is None:
- # We did fetch all records. Mark the cache to contain all info since
- # the start of time.
- oldest_info = 0
- cache.oldest_info = oldest_info
- cache.write_cache_to_disk()
-
-
-def record_reviews(cache, reviews, phab):
- most_recent_info = None
- oldest_info = None
- for reviewInfo in reviews["data"]:
- if reviewInfo["type"] != "DREV":
- continue
- id = reviewInfo["id"]
- # phid = reviewInfo["phid"]
- dateModified = int(reviewInfo["fields"]["dateModified"])
- dateCreated = int(reviewInfo["fields"]["dateCreated"])
- title = reviewInfo["fields"]["title"]
- author = reviewInfo["fields"]["authorPHID"]
- phabReview = cache.get(id)
- if (
- "dateModified" not in phabReview.__dict__
- or dateModified > phabReview.dateModified
- ):
-
diff _results = phab.
diff erential.query
diff s(revisionIDs=[id])
-
diff _ids = sorted(
diff _results.keys())
- phabDiffs = []
- for
diff _id in
diff _ids:
-
diff Info =
diff _results[
diff _id]
- d = PhabDiff(
diff _id)
- d.update(
diff Info)
- phabDiffs.append(d)
- phabReview.update(title, dateCreated, dateModified, author)
- phabReview.setPhabDiffs(phabDiffs)
- print(
- "Updated D{0} modified on {1} ({2}
diff s)".format(
- id, datetime.fromtimestamp(dateModified), len(phabDiffs)
- )
- )
-
- if most_recent_info is None:
- most_recent_info = dateModified
- elif most_recent_info < dateModified:
- most_recent_info = dateModified
-
- if oldest_info is None:
- oldest_info = dateModified
- elif oldest_info > dateModified:
- oldest_info = dateModified
- return most_recent_info, oldest_info
-
-
-def record_users(cache, users, phab):
- most_recent_info = None
- oldest_info = None
- for info in users["data"]:
- if info["type"] != "USER":
- continue
- id = info["id"]
- phid = info["phid"]
- dateModified = int(info["fields"]["dateModified"])
- # dateCreated = int(info["fields"]["dateCreated"])
- realName = info["fields"]["realName"]
- phabUser = cache.get(id)
- phabUser.update(phid, realName)
- if most_recent_info is None:
- most_recent_info = dateModified
- elif most_recent_info < dateModified:
- most_recent_info = dateModified
- if oldest_info is None:
- oldest_info = dateModified
- elif oldest_info > dateModified:
- oldest_info = dateModified
- return most_recent_info, oldest_info
-
-
-PHABCACHESINFO = (
- (
- reviews_cache,
- ("
diff erential", "revision", "search"),
- "updated",
- record_reviews,
- 5,
- 7,
- ),
- (users_cache, ("user", "search"), "newest", record_users, 100, 1000),
-)
-
-
-def load_cache():
- for cache, phab_query, order, record_results, _, _ in PHABCACHESINFO:
- cache.populate_cache_from_disk()
- print(
- "Loaded {0} nr entries: {1}".format(
- cache.get_name(), len(cache.get_ids_in_cache())
- )
- )
- print(
- "Loaded {0} has most recent info: {1}".format(
- cache.get_name(),
- datetime.fromtimestamp(cache.most_recent_info)
- if cache.most_recent_info is not None
- else None,
- )
- )
-
-
-def update_cache(phab):
- load_cache()
- for (
- cache,
- phab_query,
- order,
- record_results,
- max_nr_entries_per_fetch,
- max_nr_days_to_cache,
- ) in PHABCACHESINFO:
- update_cached_info(
- phab,
- cache,
- phab_query,
- order,
- record_results,
- max_nr_entries_per_fetch,
- max_nr_days_to_cache,
- )
- ids_in_cache = cache.get_ids_in_cache()
- print("{0} objects in {1}".format(len(ids_in_cache), cache.get_name()))
- cache.write_cache_to_disk()
-
-
-def get_most_recent_reviews(days):
- newest_reviews = sorted(reviews_cache.get_objects(), key=lambda r: -r.dateModified)
- if len(newest_reviews) == 0:
- return newest_reviews
- most_recent_review_time = datetime.fromtimestamp(newest_reviews[0].dateModified)
- cut_off_date = most_recent_review_time - timedelta(days=days)
- result = []
- for review in newest_reviews:
- if datetime.fromtimestamp(review.dateModified) < cut_off_date:
- return result
- result.append(review)
- return result
-
-
-# All of the above code is about fetching data from Phabricator and caching it
-# on local disk. The below code contains the actual "business logic" for this
-# script.
-
-_userphid2realname = None
-
-
-def get_real_name_from_author(user_phid):
- global _userphid2realname
- if _userphid2realname is None:
- _userphid2realname = {}
- for user in users_cache.get_objects():
- _userphid2realname[user.phid] = user.realName
- return _userphid2realname.get(user_phid, "unknown")
-
-
-def print_most_recent_reviews(phab, days, filter_reviewers):
- msgs = []
-
- def add_msg(msg):
- msgs.append(msg)
- print(msg.encode("utf-8"))
-
- newest_reviews = get_most_recent_reviews(days)
- add_msg(
- "These are the reviews that look interesting to be reviewed. "
- + "The report below has 2 sections. The first "
- + "section is organized per review; the second section is organized "
- + "per potential reviewer.\n"
- )
- oldest_review = newest_reviews[-1] if len(newest_reviews) > 0 else None
- oldest_datetime = (
- datetime.fromtimestamp(oldest_review.dateModified) if oldest_review else None
- )
- add_msg(
- (
- "The report below is based on analyzing the reviews that got "
- + "touched in the past {0} days (since {1}). "
- + "The script found {2} such reviews.\n"
- ).format(days, oldest_datetime, len(newest_reviews))
- )
- reviewer2reviews_and_scores = {}
- for i, review in enumerate(newest_reviews):
- matched_reviewers = find_reviewers_for_review(review)
- matched_reviewers = filter_reviewers(matched_reviewers)
- if len(matched_reviewers) == 0:
- continue
- add_msg(
- (
- "{0:>3}. https://reviews.llvm.org/D{1} by {2}\n {3}\n"
- + " Last updated on {4}"
- ).format(
- i,
- review.id,
- get_real_name_from_author(review.author),
- review.title,
- datetime.fromtimestamp(review.dateModified),
- )
- )
- for reviewer, scores in matched_reviewers:
- add_msg(
- " potential reviewer {0}, score {1}".format(
- reviewer,
- "(" + "/".join(["{0:.1f}%".format(s) for s in scores]) + ")",
- )
- )
- if reviewer not in reviewer2reviews_and_scores:
- reviewer2reviews_and_scores[reviewer] = []
- reviewer2reviews_and_scores[reviewer].append((review, scores))
-
- # Print out a summary per reviewer.
- for reviewer in sorted(reviewer2reviews_and_scores.keys()):
- reviews_and_scores = reviewer2reviews_and_scores[reviewer]
- reviews_and_scores.sort(key=lambda rs: rs[1], reverse=True)
- add_msg(
- "\n\nSUMMARY FOR {0} (found {1} reviews):".format(
- reviewer, len(reviews_and_scores)
- )
- )
- for review, scores in reviews_and_scores:
- add_msg(
- "[{0}] https://reviews.llvm.org/D{1} '{2}' by {3}".format(
- "/".join(["{0:.1f}%".format(s) for s in scores]),
- review.id,
- review.title,
- get_real_name_from_author(review.author),
- )
- )
- return "\n".join(msgs)
-
-
-def get_git_cmd_output(cmd):
- output = None
- try:
- logging.debug(cmd)
- output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
- except subprocess.CalledProcessError as e:
- logging.debug(str(e))
- if output is None:
- return None
- return output.decode("utf-8", errors="ignore")
-
-
-reAuthorMail = re.compile("^author-mail <([^>]*)>.*$")
-
-
-def parse_blame_output_line_porcelain(blame_output_lines):
- email2nr_occurences = {}
- if blame_output_lines is None:
- return email2nr_occurences
- for line in blame_output_lines:
- m = reAuthorMail.match(line)
- if m:
- author_email_address = m.group(1)
- if author_email_address not in email2nr_occurences:
- email2nr_occurences[author_email_address] = 1
- else:
- email2nr_occurences[author_email_address] += 1
- return email2nr_occurences
-
-
-class BlameOutputCache:
- def __init__(self):
- self.cache = {}
-
- def _populate_cache_for(self, cache_key):
- assert cache_key not in self.cache
- git_repo, base_revision, path = cache_key
- cmd = (
- "git -C {0} blame --encoding=utf-8 --date iso -f -e -w "
- + "--line-porcelain {1} -- {2}"
- ).format(git_repo, base_revision, path)
- blame_output = get_git_cmd_output(cmd)
- self.cache[cache_key] = (
- blame_output.split("\n") if blame_output is not None else None
- )
- # FIXME: the blame cache could probably be made more effective still if
- # instead of storing the requested base_revision in the cache, the last
- # revision before the base revision this file/path got changed in gets
- # stored. That way multiple project revisions for which this specific
- # file/patch hasn't changed would get cache hits (instead of misses in
- # the current implementation).
-
- def get_blame_output_for(
- self, git_repo, base_revision, path, start_line=-1, end_line=-1
- ):
- cache_key = (git_repo, base_revision, path)
- if cache_key not in self.cache:
- self._populate_cache_for(cache_key)
- assert cache_key in self.cache
- all_blame_lines = self.cache[cache_key]
- if all_blame_lines is None:
- return None
- if start_line == -1 and end_line == -1:
- return all_blame_lines
- assert start_line >= 0
- assert end_line >= 0
- assert end_line <= len(all_blame_lines)
- assert start_line <= len(all_blame_lines)
- assert start_line <= end_line
- return all_blame_lines[start_line:end_line]
-
- def get_parsed_git_blame_for(
- self, git_repo, base_revision, path, start_line=-1, end_line=-1
- ):
- return parse_blame_output_line_porcelain(
- self.get_blame_output_for(
- git_repo, base_revision, path, start_line, end_line
- )
- )
-
-
-blameOutputCache = BlameOutputCache()
-
-
-def find_reviewers_for_
diff _heuristic(
diff ):
- # Heuristic 1: assume good reviewers are the ones that touched the same
- # lines before as this patch is touching.
- # Heuristic 2: assume good reviewers are the ones that touched the same
- # files before as this patch is touching.
- reviewers2nr_lines_touched = {}
- reviewers2nr_files_touched = {}
- # Assume last revision before
diff was modified is the revision the
diff
- # applies to.
- assert len(GIT_REPO_METADATA) == 1
- git_repo = os.path.join("git_repos", GIT_REPO_METADATA[0][0])
- cmd = 'git -C {0} rev-list -n 1 --before="{1}" main'.format(
- git_repo,
- datetime.fromtimestamp(
diff .dateModified).strftime("%Y-%m-%d %H:%M:%s"),
- )
- base_revision = get_git_cmd_output(cmd).strip()
- logging.debug("Base revision={0}".format(base_revision))
- for change in
diff .changes:
- path = change.oldPath
- # Compute heuristic 1: look at context of patch lines.
- for hunk in change.hunks:
- for start_line, end_line in hunk.actual_lines_changed_offset:
- # Collect git blame results for authors in those ranges.
- for (
- reviewer,
- nr_occurences,
- ) in blameOutputCache.get_parsed_git_blame_for(
- git_repo, base_revision, path, start_line, end_line
- ).items():
- if reviewer not in reviewers2nr_lines_touched:
- reviewers2nr_lines_touched[reviewer] = 0
- reviewers2nr_lines_touched[reviewer] += nr_occurences
- # Compute heuristic 2: don't look at context, just at files touched.
- # Collect git blame results for authors in those ranges.
- for reviewer, nr_occurences in blameOutputCache.get_parsed_git_blame_for(
- git_repo, base_revision, path
- ).items():
- if reviewer not in reviewers2nr_files_touched:
- reviewers2nr_files_touched[reviewer] = 0
- reviewers2nr_files_touched[reviewer] += 1
-
- # Compute "match scores"
- total_nr_lines = sum(reviewers2nr_lines_touched.values())
- total_nr_files = len(
diff .changes)
- reviewers_matchscores = [
- (
- reviewer,
- (
- reviewers2nr_lines_touched.get(reviewer, 0) * 100.0 / total_nr_lines
- if total_nr_lines != 0
- else 0,
- reviewers2nr_files_touched[reviewer] * 100.0 / total_nr_files
- if total_nr_files != 0
- else 0,
- ),
- )
- for reviewer, nr_lines in reviewers2nr_files_touched.items()
- ]
- reviewers_matchscores.sort(key=lambda i: i[1], reverse=True)
- return reviewers_matchscores
-
-
-def find_reviewers_for_review(review):
- # Process the newest
diff first.
-
diff s = sorted(review.phabDiffs, key=lambda d: d.dateModified, reverse=True)
- if len(
diff s) == 0:
- return
-
diff =
diff s[0]
- matched_reviewers = find_reviewers_for_
diff _heuristic(
diff )
- # Show progress, as this is a slow operation:
- sys.stdout.write(".")
- sys.stdout.flush()
- logging.debug("matched_reviewers: {0}".format(matched_reviewers))
- return matched_reviewers
-
-
-def update_git_repos():
- git_repos_directory = "git_repos"
- for name, url in GIT_REPO_METADATA:
- dirname = os.path.join(git_repos_directory, name)
- if not os.path.exists(dirname):
- cmd = "git clone {0} {1}".format(url, dirname)
- output = get_git_cmd_output(cmd)
- cmd = "git -C {0} pull --rebase".format(dirname)
- output = get_git_cmd_output(cmd)
-
-
-def send_emails(email_addresses, sender, msg):
- s = smtplib.SMTP()
- s.connect()
- for email_address in email_addresses:
- email_msg = email.mime.multipart.MIMEMultipart()
- email_msg["From"] = sender
- email_msg["To"] = email_address
- email_msg["Subject"] = "LLVM patches you may be able to review."
- email_msg.attach(email.mime.text.MIMEText(msg.encode("utf-8"), "plain"))
- # python 3.x: s.send_message(email_msg)
- s.sendmail(email_msg["From"], email_msg["To"], email_msg.as_string())
- s.quit()
-
-
-def filter_reviewers_to_report_for(people_to_look_for):
- # The below is just an example filter, to only report potential reviews
- # to do for the people that will receive the report email.
- return lambda potential_reviewers: [
- r for r in potential_reviewers if r[0] in people_to_look_for
- ]
-
-
-def main():
- parser = argparse.ArgumentParser(
- description="Match open reviews to potential reviewers."
- )
- parser.add_argument(
- "--no-update-cache",
- dest="update_cache",
- action="store_false",
- default=True,
- help="Do not update cached Phabricator objects",
- )
- parser.add_argument(
- "--email-report",
- dest="email_report",
- nargs="*",
- default="",
- help="A email addresses to send the report to.",
- )
- parser.add_argument(
- "--sender",
- dest="sender",
- default="",
- help="The email address to use in 'From' on messages emailed out.",
- )
- parser.add_argument(
- "--email-addresses",
- dest="email_addresses",
- nargs="*",
- help="The email addresses (as known by LLVM git) of "
- + "the people to look for reviews for.",
- )
- parser.add_argument("--verbose", "-v", action="count")
-
- args = parser.parse_args()
-
- if args.verbose >= 1:
- logging.basicConfig(level=logging.DEBUG)
-
- people_to_look_for = [e.decode("utf-8") for e in args.email_addresses]
- logging.debug(
- "Will look for reviews that following contributors could "
- + "review: {}".format(people_to_look_for)
- )
- logging.debug("Will email a report to: {}".format(args.email_report))
-
- phab = init_phab_connection()
-
- if args.update_cache:
- update_cache(phab)
-
- load_cache()
- update_git_repos()
- msg = print_most_recent_reviews(
- phab,
- days=1,
- filter_reviewers=filter_reviewers_to_report_for(people_to_look_for),
- )
-
- if args.email_report != []:
- send_emails(args.email_report, args.sender, msg)
-
-
-if __name__ == "__main__":
- main()
More information about the llvm-commits
mailing list