Пример #1
0
def parseReviewFilters(db, data):
    reviewfilters = []

    for filter_data in data:
        filter_username = filter_data["username"]
        filter_type = filter_data["type"]
        filter_path = filter_data["path"]

        filter_user = dbutils.User.fromName(db, filter_username)
        if not filter_user:
            raise OperationError("no such user: '******'" % filter_username)

        filter_directory_id = 0
        filter_file_id = 0

        if filter_path != "/":
            if filter_path[-1] == "/" or dbutils.is_directory(filter_path):
                filter_directory_id = dbutils.find_directory(db,
                                                             path=filter_path)
            else:
                filter_file_id = dbutils.find_file(db, path=filter_path)

        reviewfilters.append((filter_directory_id, filter_file_id, filter_type,
                              None, filter_user.id))

    return reviewfilters
Пример #2
0
    def process(self, db, creator, review_id, filters):
        review = dbutils.Review.fromId(db, review_id)
        by_user = {}

        for filter in filters:
            if "user_ids" in filter:
                user_ids = set(filter["user_ids"])
            else:
                user_ids = set([])

            if "user_names" in filter:
                for user_name in filter["user_names"]:
                    user_ids.add(dbutils.User.fromName(db, user_name).id)

            if "directory_ids" in filter:
                directory_ids = set(filter["directory_ids"])
            else:
                directory_ids = set([])

            if "file_ids" in filter:
                file_ids = set(filter["file_ids"])
            else:
                file_ids = set([])

            if "paths" in filter:
                for path in filter["paths"]:
                    if not path or path == "/":
                        directory_ids.add(0)
                    elif path.endswith("/") or dbutils.is_directory(
                            db, path) or ("." not in path.split("/")[-1]
                                          and not dbutils.is_file(db, path)):
                        directory_ids.add(dbutils.find_directory(db, path))
                    else:
                        file_ids.add(dbutils.find_file(db, path))

            for user_id in user_ids:
                reviewer_directory_ids, reviewer_file_ids, watcher_directory_ids, watcher_file_ids = by_user.setdefault(
                    user_id, (set(), set(), set(), set()))

                if filter["type"] == "reviewer":
                    reviewer_directory_ids |= directory_ids
                    reviewer_file_ids |= file_ids
                else:
                    watcher_directory_ids |= directory_ids
                    watcher_file_ids |= file_ids

        pending_mails = []

        for user_id, args in by_user.items():
            user = dbutils.User.fromId(db, user_id)
            pending_mails.extend(
                review_utils.addReviewFilters(db, creator, user, review,
                                              *args))

        db.commit()

        mailutils.sendPendingMails(pending_mails)

        return OperationResult()
Пример #3
0
def showfilters(req, db, user):
    user = dbutils.User.fromName(db, req.getParameter("user", req.user))
    path = req.getParameter("path")
    repository = gitutils.Repository.fromParameter(db, req.getParameter("repository", user.getPreference(db, "defaultRepository")))

    path = path.rstrip("/")

    if dbutils.is_directory(db, path):
        directory_id = dbutils.find_directory(db, path=path)
        show_path = path + "/"

        cursor = db.cursor()
        cursor.execute("SELECT name FROM files WHERE directory=%s ORDER BY id ASC LIMIT 1", (directory_id,))

        row = cursor.fetchone()
        if row: path += "/" + row[0]
        else: path += "/dummy.txt"
    else:
        show_path = path

    file_id = dbutils.find_file(db, path=path)

    filters = review_filters.Filters()
    filters.load(db, repository=repository, recursive=True)

    reviewers = []
    watchers = []

    for user_id, (filter_type, _delegate) in filters.listUsers(db, file_id).items():
        if filter_type == 'reviewer': reviewers.append(user_id)
        else: watchers.append(user_id)

    result = "Path: %s\n" % show_path

    reviewers_found = False
    watchers_found = False

    for reviewer_id in sorted(reviewers):
        if not reviewers_found:
            result += "\nReviewers:\n"
            reviewers_found = True

        reviewer = dbutils.User.fromId(db, reviewer_id)
        result += "  %s <%s>\n" % (reviewer.fullname, reviewer.email)

    for watcher_id in sorted(watchers):
        if not watchers_found:
            result += "\nWatchers:\n"
            watchers_found = True

        watcher = dbutils.User.fromId(db, watcher_id)
        result += "  %s <%s>\n" % (watcher.fullname, watcher.email)

    if not reviewers_found and not watchers_found:
        result += "\nNo matching filters found.\n"

    return result
Пример #4
0
    def process(self, db, creator, review_id, filters):
        review = dbutils.Review.fromId(db, review_id)
        by_user = {}

        for filter in filters:
            if "user_ids" in filter:
                user_ids = set(filter["user_ids"])
            else:
                user_ids = set([])

            if "user_names" in filter:
                for user_name in filter["user_names"]:
                    user_ids.add(dbutils.User.fromName(db, user_name).id)

            if "directory_ids" in filter:
                directory_ids = set(filter["directory_ids"])
            else:
                directory_ids = set([])

            if "file_ids" in filter:
                file_ids = set(filter["file_ids"])
            else:
                file_ids = set([])

            if "paths" in filter:
                for path in filter["paths"]:
                    if not path or path == "/":
                        directory_ids.add(0)
                    elif path.endswith("/") or dbutils.is_directory(db, path) or ("." not in path.split("/")[-1] and not dbutils.is_file(db, path)):
                        directory_ids.add(dbutils.find_directory(db, path))
                    else:
                        file_ids.add(dbutils.find_file(db, path))

            for user_id in user_ids:
                reviewer_directory_ids, reviewer_file_ids, watcher_directory_ids, watcher_file_ids = by_user.setdefault(user_id, (set(), set(), set(), set()))

                if filter["type"] == "reviewer":
                    reviewer_directory_ids |= directory_ids
                    reviewer_file_ids |= file_ids
                else:
                    watcher_directory_ids |= directory_ids
                    watcher_file_ids |= file_ids

        pending_mails = []

        for user_id, args in by_user.items():
            user = dbutils.User.fromId(db, user_id)
            pending_mails.extend(review_utils.addReviewFilters(db, creator, user, review, *args))

        db.commit()

        mailutils.sendPendingMails(pending_mails)

        return OperationResult()
Пример #5
0
def addfilter(req, db, user):
    if user.isAnonymous(): return OperationFailureMustLogin()

    cursor = db.cursor()

    repository_id = req.getParameter("repository", filter=int)
    filter_type = req.getParameter("type")
    filter_path = req.getParameter("path")
    filter_delegate = req.getParameter("delegate", "")
    force = req.getParameter("force", "no") == "yes"

    repository = gitutils.Repository.fromId(db, repository_id)

    if filter_delegate:
        invalid_users = []
        for delegate_name in map(str.strip, filter_delegate.split(',')):
            if dbutils.User.fromName(db, delegate_name) is None:
                invalid_users.append(delegate_name)
        if invalid_users: return "error:invalid-users:%s" % ','.join(invalid_users)

    if filter_path == '/':
        directory_id, file_id = 0, 0
    elif filter_path[-1] == '/':
        directory_id, file_id = dbutils.find_directory(db, path=filter_path[:-1]), 0
    else:
        if not force and dbutils.is_directory(db, filter_path): return "error:directory"
        else: directory_id, file_id = dbutils.find_directory_file(db, filter_path)

    if directory_id:
        specificity = len(dbutils.explode_path(db, directory_id=directory_id))
        if file_id: specificity += 1
    else:
        specificity = 0

    cursor.execute("INSERT INTO filters (uid, repository, directory, file, specificity, type, delegate) VALUES (%s, %s, %s, %s, %s, %s, %s)", [user.id, repository.id, directory_id, file_id, specificity, filter_type, ','.join(map(str.strip, filter_delegate.split(',')))])
    user.setPreference(db, "email.activated", True)

    db.commit()

    return "ok:directory=%d,file=%d" % (directory_id, file_id)
Пример #6
0
def parseReviewFilters(db, data):
    reviewfilters = []

    for filter_data in data:
        filter_username = filter_data["username"]
        filter_type = filter_data["type"]
        filter_path = filter_data["path"]

        filter_user = dbutils.User.fromName(db, filter_username)
        if not filter_user:
            raise OperationError("no such user: '******'" % filter_username)

        filter_directory_id = 0
        filter_file_id = 0

        if filter_path != "/":
            if filter_path[-1] == "/" or dbutils.is_directory(filter_path):
                filter_directory_id = dbutils.find_directory(db, path=filter_path)
            else:
                filter_file_id = dbutils.find_file(db, path=filter_path)

        reviewfilters.append((filter_directory_id, filter_file_id, filter_type, None, filter_user.id))

    return reviewfilters
Пример #7
0
def renderSearch(req, db, user):
    summary_value = req.getParameter("summary", None)
    summary_mode_value = req.getParameter("summarymode", None)
    branch_value = req.getParameter("branch", None)
    owner_value = req.getParameter("owner", None)
    path_value = req.getParameter("path", None)

    document = htmlutils.Document(req)
    document.setTitle("Search")

    html = document.html()
    head = html.head()
    body = html.body()

    page.utils.generateHeader(body, db, user, current_page="search")

    document.addExternalStylesheet("resource/search.css")
    document.addExternalScript("resource/search.js")
    document.addInternalScript(user.getJS())

    cursor = db.cursor()
    cursor.execute("SELECT DISTINCT name, fullname FROM users JOIN reviewusers ON (reviewusers.uid=users.id) WHERE reviewusers.owner")

    users = [("{ label: %s, value: %s }" % (htmlutils.jsify("%s (%s)" % (fullname, name)),
                                            htmlutils.jsify(name)))
             for name, fullname in cursor]

    document.addInternalScript("var users = [ %s ];" % ", ".join(users))

    search = page.utils.PaleYellowTable(body, "Search")

    def renderSummary(target):
        target.input(name="summary", value=summary_value or "")
        summary_mode = target.select(name="summary_mode")
        summary_mode.option(value="all", selected="selected" if summary_mode_value == "all" else None).text("All words")
        summary_mode.option(value="any", selected="selected" if summary_mode_value == "any" else None).text("Any word")

    def renderBranch(target):
        target.input(name="branch", value=branch_value or "")

    def renderOwner(target):
        target.input(name="owner", value=owner_value or "")

    def renderPath(target):
        target.input(name="path", value=path_value or "")

    def renderButton(target):
        target.button(onclick="search();").text("Search")

    search.addItem("Summary", renderSummary, "Words occurring in the review's summary.")
    search.addItem("Branch", renderBranch, "Name of review branch.")
    search.addItem("Owner", renderOwner, "Owner of the review.")
    search.addItem("Path", renderPath, "Path (file or directory) that the review contains changes in.")
    search.addCentered(renderButton)

    if summary_value is not None: summary_value = summary_value.strip()
    if branch_value is not None: branch_value = branch_value.strip()
    if owner_value is not None: owner_value = owner_value.strip()
    if path_value is not None: path_value = path_value.strip()

    if summary_value or branch_value or owner_value or path_value:
        query = """SELECT DISTINCT reviews.id, reviews.summary, branches.name
                     FROM %s
                    WHERE %s"""

        tables = ["reviews", "branches ON (branches.id=reviews.branch)"]
        conditions = []
        arguments = []

        if summary_value:
            words = summary_value.split()
            operator = " AND " if summary_mode_value == "all" else " OR "
            conditions.append("(%s)" % operator.join(["reviews.summary ~* %s"] * len(words)))
            arguments.extend([".*\\m" + word + "\\M.*" for word in words])

        if branch_value:
            def globToSQLPattern(glob):
                pattern = glob.replace("\\", "\\\\").replace("%", "\\%").replace("?", "_").replace("*", "%")
                if pattern[0] != "%": pattern = "%" + pattern
                if pattern[-1] != "%": pattern = pattern + "%"
                return pattern

            conditions.append("branches.name LIKE %s")
            arguments.append(globToSQLPattern(branch_value))

        if owner_value:
            owner = dbutils.User.fromName(db, owner_value)
            tables.append("reviewusers ON (reviewusers.review=reviews.id)")
            conditions.append("reviewusers.uid=%s")
            conditions.append("reviewusers.owner")
            arguments.append(owner.id)

        if path_value:
            file_ids = dbutils.contained_files(db, dbutils.find_directory(db, path_value))

            if path_value[-1] != '/':
                file_ids.append(dbutils.find_file(db, path_value))

            tables.append("reviewfiles ON (reviewfiles.review=reviews.id)")
            conditions.append("reviewfiles.file=ANY (%s)")
            arguments.append(file_ids)

        query = """SELECT DISTINCT reviews.id, reviews.summary, branches.name
                     FROM %s
                    WHERE %s
                 ORDER BY reviews.id""" % (" JOIN ".join(tables), " AND ".join(conditions))

        cursor.execute(query, arguments)

        table = body.div("main").table("paleyellow reviews", align="center")
        table.col(width="20%")
        table.col(width="80%")
        header = table.tr().td("h1", colspan=4).h1()
        header.text("Reviews")

        for review_id, summary, branch_name in cursor:
            row = table.tr("review")
            row.td("name").text(branch_name)
            row.td("title").a(href="r/%d" % review_id).text(summary)

    return document
Пример #8
0
                modules.add(moduleFromFile(file_id))
            teams_per_modules.setdefault(frozenset(modules), set()).update(team)

        for modules, team in teams_per_modules.items():
            row = shared.tr("reviewers")

            cell = row.td("reviewers")
            members = sorted([dbutils.User.fromId(db, user_id).fullname for user_id in team])
            for member in members: cell.text(member).br()
            row.td("willreview").innerHTML("<span class='also'>also</span>&nbsp;review&nbsp;changes&nbsp;in")

            cell = row.td("files")
            for path in diff.File.eliminateCommonPrefixes(sorted(modules)):
                cell.span("file").innerHTML(path).br()

            directory_ids = "[ %s ]" % ", ".join([str(dbutils.find_directory(db, path=path[:-1])) for path in modules if path.endswith("/")])
            file_ids = "[ %s ]" % ", ".join([str(dbutils.find_file(db, path=path)) for path in modules if not path.endswith("/")])
            user_ids = "[ %s ]" % ", ".join(map(str, team))

            cell = row.td("buttons")
            cell.button("accept", critic_directory_ids=directory_ids, critic_file_ids=file_ids, critic_user_ids=user_ids).text("I will review this!")
            cell.button("deny", critic_directory_ids=directory_ids, critic_file_ids=file_ids, critic_user_ids=user_ids).text("They will review this!")

    yield flush(target)

    profiler.check("shared assignments")

    cursor.execute("SELECT batches.id, users.fullname, batches.comment, batches.time FROM batches JOIN users ON (users.id=batches.uid) WHERE batches.review=%s ORDER BY batches.id DESC", [review.id])
    rows = cursor.fetchall()

    if rows:
Пример #9
0
                modules.add(moduleFromFile(file_id))
            teams_per_modules.setdefault(frozenset(modules), set()).update(team)

        for modules, team in teams_per_modules.items():
            row = shared.tr("reviewers")

            cell = row.td("reviewers")
            members = sorted([dbutils.User.fromId(db, user_id).fullname for user_id in team])
            for member in members: cell.text(member).br()
            row.td("willreview").innerHTML("<span class='also'>also</span>&nbsp;review&nbsp;changes&nbsp;in")

            cell = row.td("files")
            for path in diff.File.eliminateCommonPrefixes(sorted(modules)):
                cell.span("file").innerHTML(path).br()

            directory_ids = "[ %s ]" % ", ".join([str(dbutils.find_directory(db, path=path[:-1])) for path in modules if path.endswith("/")])
            file_ids = "[ %s ]" % ", ".join([str(dbutils.find_file(db, path=path)) for path in modules if not path.endswith("/")])
            user_ids = "[ %s ]" % ", ".join(map(str, team))

            cell = row.td("buttons")
            cell.button("accept", critic_directory_ids=directory_ids, critic_file_ids=file_ids, critic_user_ids=user_ids).text("I will review this!")
            cell.button("deny", critic_directory_ids=directory_ids, critic_file_ids=file_ids, critic_user_ids=user_ids).text("They will review this!")

    yield flush(target)

    profiler.check("shared assignments")

    cursor.execute("SELECT batches.id, users.fullname, batches.comment, batches.time FROM batches JOIN users ON (users.id=batches.uid) WHERE batches.review=%s ORDER BY batches.id DESC", [review.id])
    rows = cursor.fetchall()

    if rows:
Пример #10
0
def renderSearch(req, db, user):
    summary_value = req.getParameter("summary", None)
    summary_mode_value = req.getParameter("summarymode", None)
    branch_value = req.getParameter("branch", None)
    owner_value = req.getParameter("owner", None)
    path_value = req.getParameter("path", None)

    document = htmlutils.Document(req)
    document.setTitle("Search")

    html = document.html()
    head = html.head()
    body = html.body()

    page.utils.generateHeader(body, db, user, current_page="search")

    document.addExternalStylesheet("resource/search.css")
    document.addExternalScript("resource/search.js")
    document.addInternalScript(user.getJS())

    cursor = db.cursor()
    cursor.execute(
        "SELECT DISTINCT name, fullname FROM users JOIN reviewusers ON (reviewusers.uid=users.id) WHERE reviewusers.owner"
    )

    users = [("{ label: %s, value: %s }" %
              (htmlutils.jsify("%s (%s)" %
                               (fullname, name)), htmlutils.jsify(name)))
             for name, fullname in cursor]

    document.addInternalScript("var users = [ %s ];" % ", ".join(users))

    search = page.utils.PaleYellowTable(body, "Search")

    def renderSummary(target):
        target.input(name="summary", value=summary_value or "")
        summary_mode = target.select(name="summary_mode")
        summary_mode.option(value="all",
                            selected="selected" if summary_mode_value == "all"
                            else None).text("All words")
        summary_mode.option(value="any",
                            selected="selected" if summary_mode_value == "any"
                            else None).text("Any word")

    def renderBranch(target):
        target.input(name="branch", value=branch_value or "")

    def renderOwner(target):
        target.input(name="owner", value=owner_value or "")

    def renderPath(target):
        target.input(name="path", value=path_value or "")

    def renderButton(target):
        target.button(onclick="search();").text("Search")

    search.addItem("Summary", renderSummary,
                   "Words occurring in the review's summary.")
    search.addItem("Branch", renderBranch, "Name of review branch.")
    search.addItem("Owner", renderOwner, "Owner of the review.")
    search.addItem(
        "Path", renderPath,
        "Path (file or directory) that the review contains changes in.")
    search.addCentered(renderButton)

    if summary_value is not None: summary_value = summary_value.strip()
    if branch_value is not None: branch_value = branch_value.strip()
    if owner_value is not None: owner_value = owner_value.strip()
    if path_value is not None: path_value = path_value.strip()

    if summary_value or branch_value or owner_value or path_value:
        query = """SELECT DISTINCT reviews.id, reviews.summary, branches.name
                     FROM %s
                    WHERE %s"""

        tables = ["reviews", "branches ON (branches.id=reviews.branch)"]
        conditions = []
        arguments = []

        if summary_value:
            words = summary_value.split()
            operator = " AND " if summary_mode_value == "all" else " OR "
            conditions.append(
                "(%s)" % operator.join(["reviews.summary ~* %s"] * len(words)))
            arguments.extend([".*\\m" + word + "\\M.*" for word in words])

        if branch_value:

            def globToSQLPattern(glob):
                pattern = glob.replace("\\",
                                       "\\\\").replace("%", "\\%").replace(
                                           "?", "_").replace("*", "%")
                if pattern[0] != "%": pattern = "%" + pattern
                if pattern[-1] != "%": pattern = pattern + "%"
                return pattern

            conditions.append("branches.name LIKE %s")
            arguments.append(globToSQLPattern(branch_value))

        if owner_value:
            owner = dbutils.User.fromName(db, owner_value)
            tables.append("reviewusers ON (reviewusers.review=reviews.id)")
            conditions.append("reviewusers.uid=%s")
            conditions.append("reviewusers.owner")
            arguments.append(owner.id)

        if path_value:
            file_ids = dbutils.contained_files(
                db, dbutils.find_directory(db, path_value))

            if path_value[-1] != '/':
                file_ids.append(dbutils.find_file(db, path_value))

            tables.append("reviewfiles ON (reviewfiles.review=reviews.id)")
            conditions.append("reviewfiles.file=ANY (%s)")
            arguments.append(file_ids)

        query = """SELECT DISTINCT reviews.id, reviews.summary, branches.name
                     FROM %s
                    WHERE %s
                 ORDER BY reviews.id""" % (" JOIN ".join(tables),
                                           " AND ".join(conditions))

        cursor.execute(query, arguments)

        table = body.div("main").table("paleyellow reviews", align="center")
        table.col(width="20%")
        table.col(width="80%")
        header = table.tr().td("h1", colspan=4).h1()
        header.text("Reviews")

        for review_id, summary, branch_name in cursor:
            row = table.tr("review")
            row.td("name").text(branch_name)
            row.td("title").a(href="r/%d" % review_id).text(summary)

    return document