Exemple #1
0
def createReview(db, user, repository, commits, branch_name, summary, description, from_branch_name=None, via_push=False, reviewfilters=None, applyfilters=True, applyparentfilters=False, recipientfilters=None):
    cursor = db.cursor()

    if via_push:
        applyparentfilters = bool(user.getPreference(db, 'review.applyUpstreamFilters'))

    branch = dbutils.Branch.fromName(db, repository, branch_name)

    if branch is not None:
        raise OperationFailure(
            code="branchexists",
            title="Invalid review branch name",
            message="""\
<p>There is already a branch named <code>%s</code> in the repository.  You have
to select a different name.</p>

<p>If you believe the existing branch was created during an earlier (failed)
attempt to create this review, you can try to delete it from the repository
using the command<p>

<pre>  git push &lt;remote&gt; :%s</pre>

<p>and then press the "Submit Review" button on this page again."""
            % (htmlutils.htmlify(branch_name), htmlutils.htmlify(branch_name)),
            is_html=True)

    if not commits:
        raise OperationFailure(
            code="nocommits",
            title="No commits specified",
            message="You need at least one commit to create a review.")

    commitset = log_commitset.CommitSet(commits)
    heads = commitset.getHeads()

    if len(heads) != 1:
        # There is really no plausible way for this error to occur.
        raise OperationFailure(
            code="disconnectedtree",
            title="Disconnected tree",
            message=("The specified commits do do not form a single connected "
                     "tree.  Creating a review of them is not supported."))

    head = heads.pop()

    if len(commitset.getTails()) != 1:
        tail_id = None
    else:
        tail_id = gitutils.Commit.fromSHA1(db, repository, commitset.getTails().pop()).getId(db)

    if not via_push:
        try:
            repository.createBranch(branch_name, head.sha1)
        except gitutils.GitCommandError as error:
            raise OperationFailure(
                code="branchfailed",
                title="Failed to create review branch",
                message=("<p><b>Output from git:</b></p>"
                         "<code style='padding-left: 1em'>%s</code>"
                         % htmlutils.htmlify(error.output)),
                is_html=True)

    try:
        cursor.execute("INSERT INTO branches (repository, name, head, tail, type) VALUES (%s, %s, %s, %s, 'review') RETURNING id", [repository.id, branch_name, head.getId(db), tail_id])

        branch_id = cursor.fetchone()[0]
        reachable_values = [(branch_id, commit.getId(db)) for commit in commits]

        cursor.executemany("INSERT INTO reachable (branch, commit) VALUES (%s, %s)", reachable_values)

        cursor.execute("INSERT INTO reviews (type, branch, state, summary, description, applyfilters, applyparentfilters) VALUES ('official', %s, 'open', %s, %s, %s, %s) RETURNING id", (branch_id, summary, description, applyfilters, applyparentfilters))

        review = dbutils.Review.fromId(db, cursor.fetchone()[0])

        cursor.execute("INSERT INTO reviewusers (review, uid, owner) VALUES (%s, %s, TRUE)", (review.id, user.id))

        if reviewfilters is not None:
            cursor.executemany("""INSERT INTO reviewfilters (review, uid, path, type, creator)
                                       VALUES (%s, %s, %s, %s, %s)""",
                               [(review.id, filter_user_id, filter_path, filter_type, user.id)
                                for filter_user_id, filter_path, filter_type, filter_delegate in reviewfilters])

        is_opt_in = False

        if recipientfilters is not None:
            cursor.executemany("INSERT INTO reviewrecipientfilters (review, uid, include) VALUES (%s, %s, %s)",
                               [(review.id, filter_user_id, filter_include)
                                for filter_user_id, filter_include in recipientfilters])

            for filter_user_id, filter_include in recipientfilters:
                if filter_user_id is None and not filter_include:
                    is_opt_in = True

        addCommitsToReview(db, user, review, commits, new_review=True)

        if from_branch_name is not None:
            cursor.execute("UPDATE branches SET review=%s WHERE repository=%s AND name=%s", (review.id, repository.id, from_branch_name))

        # Reload to get list of changesets added by addCommitsToReview().
        review = dbutils.Review.fromId(db, review.id)

        pending_mails = []
        recipients = review.getRecipients(db)
        for to_user in recipients:
            pending_mails.extend(mail.sendReviewCreated(db, user, to_user, recipients, review))

        if not is_opt_in:
            recipient_by_id = dict((to_user.id, to_user) for to_user in recipients)

            cursor.execute("""SELECT userpreferences.uid, userpreferences.repository,
                                     userpreferences.filter, userpreferences.integer
                                FROM userpreferences
                     LEFT OUTER JOIN filters ON (filters.id=userpreferences.filter)
                               WHERE userpreferences.item='review.defaultOptOut'
                                 AND userpreferences.uid=ANY (%s)
                                 AND (userpreferences.filter IS NULL
                                   OR filters.repository=%s)
                                 AND (userpreferences.repository IS NULL
                                   OR userpreferences.repository=%s)""",
                           (recipient_by_id.keys(), repository.id, repository.id))

            user_settings = {}
            has_filter_settings = False

            for user_id, repository_id, filter_id, integer in cursor:
                settings = user_settings.setdefault(user_id, [None, None, {}])
                value = bool(integer)

                if repository_id is None and filter_id is None:
                    settings[0] = value
                elif repository_id is not None:
                    settings[1] = value
                else:
                    settings[2][filter_id] = value
                    has_filter_settings = True

            if has_filter_settings:
                filters = Filters()
                filters.setFiles(db, review=review)

            for user_id, (global_default, repository_default, filter_settings) in user_settings.items():
                to_user = recipient_by_id[user_id]
                opt_out = None

                if repository_default is not None:
                    opt_out = repository_default
                elif global_default is not None:
                    opt_out = global_default

                if filter_settings:
                    # Policy:
                    #
                    # If all of the user's filters that matched files in the
                    # review have review.defaultOptOut enabled, then opt out.
                    # When determining this, any review filters of the user's
                    # that match files in the review count as filters that don't
                    # have the review.defaultOptOut enabled.
                    #
                    # If any of the user's filters that matched files in the
                    # review have review.defaultOptOut disabled, then don't opt
                    # out.  When determining this, review filters are ignored.
                    #
                    # Otherwise, ignore the filter settings, and go with either
                    # the user's per-repository or global setting (as set
                    # above.)

                    filters.load(db, review=review, user=to_user)

                    # A set of filter ids.  If None is in the set, the user has
                    # one or more review filters in the review.  (These do not
                    # have ids.)
                    active_filters = filters.getActiveFilters(to_user)

                    for filter_id in active_filters:
                        if filter_id is None:
                            continue
                        elif filter_id in filter_settings:
                            if not filter_settings[filter_id]:
                                opt_out = False
                                break
                        else:
                            break
                    else:
                        if None not in active_filters:
                            opt_out = True

                if opt_out:
                    cursor.execute("""INSERT INTO reviewrecipientfilters (review, uid, include)
                                           VALUES (%s, %s, FALSE)""",
                                   (review.id, to_user.id))

        db.commit()

        mail.sendPendingMails(pending_mails)

        return review
    except:
        if not via_push:
            repository.run("branch", "-D", branch_name)
        raise
Exemple #2
0
def createReview(db, user, repository, commits, branch_name, summary, description, from_branch_name=None, via_push=False, reviewfilters=None, applyfilters=True, applyparentfilters=False, recipientfilters=None):
    cursor = db.cursor()

    if via_push:
        applyparentfilters = bool(user.getPreference(db, 'review.applyUpstreamFilters'))

    branch = dbutils.Branch.fromName(db, repository, branch_name)

    if branch is not None:
        raise OperationFailure(code="branchexists",
                               title="Invalid review branch name",
                               message="""\
<p>There is already a branch named <code>%s</code> in the repository.  You have
to select a different name.</p>

<p>If you believe the existing branch was created during an earlier (failed)
attempt to create this review, you can try to delete it from the repository
using the command<p>

<pre>  git push &lt;remote&gt; :%s</pre>

<p>and then press the "Submit Review" button on this page again."""
                               % (htmlutils.htmlify(branch_name), htmlutils.htmlify(branch_name)),
                               is_html=True)

    commitset = log_commitset.CommitSet(commits)

    if len(commitset.getHeads()) != 1:
        raise Exception, "invalid commit-set; multiple heads"

    head = commitset.getHeads().pop()

    if len(commitset.getTails()) != 1:
        tail_id = None
    else:
        tail_id = gitutils.Commit.fromSHA1(db, repository, commitset.getTails().pop()).getId(db)

    if not via_push:
        repository.branch(branch_name, head.sha1)

    try:
        cursor.execute("INSERT INTO branches (repository, name, head, tail, type) VALUES (%s, %s, %s, %s, 'review') RETURNING id", [repository.id, branch_name, head.getId(db), tail_id])

        branch_id = cursor.fetchone()[0]
        reachable_values = [(branch_id, commit.getId(db)) for commit in commits]

        cursor.executemany("INSERT INTO reachable (branch, commit) VALUES (%s, %s)", reachable_values)

        cursor.execute("INSERT INTO reviews (type, branch, state, summary, description, applyfilters, applyparentfilters) VALUES ('official', %s, 'open', %s, %s, %s, %s) RETURNING id", (branch_id, summary, description, applyfilters, applyparentfilters))

        review = dbutils.Review.fromId(db, cursor.fetchone()[0])

        cursor.execute("INSERT INTO reviewusers (review, uid, owner) VALUES (%s, %s, TRUE)", (review.id, user.id))

        if reviewfilters is not None:
            cursor.executemany("INSERT INTO reviewfilters (review, uid, directory, file, type, creator) VALUES (%s, %s, %s, %s, %s, %s)",
                               [(review.id, filter_user_id, filter_directory_id, filter_file_id, filter_type, user.id)
                                for filter_directory_id, filter_file_id, filter_type, filter_delegate, filter_user_id in reviewfilters])

        if recipientfilters is not None:
            cursor.executemany("INSERT INTO reviewrecipientfilters (review, uid, include) VALUES (%s, %s, %s)",
                               [(review.id, filter_user_id, filter_include)
                                for filter_user_id, filter_include in recipientfilters])

        addCommitsToReview(db, user, review, commits, new_review=True)

        if from_branch_name is not None:
            cursor.execute("UPDATE branches SET review=%s WHERE repository=%s AND name=%s", (review.id, repository.id, from_branch_name))

        # Reload to get list of changesets added by addCommitsToReview().
        review = dbutils.Review.fromId(db, review.id)

        pending_mails = []
        recipients = review.getRecipients(db)
        for to_user in recipients:
            pending_mails.extend(mail.sendReviewCreated(db, user, to_user, recipients, review))

        db.commit()

        mail.sendPendingMails(pending_mails)

        return review
    except:
        if not via_push:
            repository.run("branch", "-D", branch_name)
        raise
Exemple #3
0
def createReview(
    db,
    user,
    repository,
    commits,
    branch_name,
    summary,
    description,
    from_branch_name=None,
    via_push=False,
    reviewfilters=None,
    applyfilters=True,
    applyparentfilters=False,
    recipientfilters=None,
):
    cursor = db.cursor()

    if via_push:
        applyparentfilters = bool(user.getPreference(db, "review.applyUpstreamFilters"))

    branch = dbutils.Branch.fromName(db, repository, branch_name)

    if branch is not None:
        raise OperationFailure(
            code="branchexists",
            title="Invalid review branch name",
            message="""\
<p>There is already a branch named <code>%s</code> in the repository.  You have
to select a different name.</p>

<p>If you believe the existing branch was created during an earlier (failed)
attempt to create this review, you can try to delete it from the repository
using the command<p>

<pre>  git push &lt;remote&gt; :%s</pre>

<p>and then press the "Submit Review" button on this page again."""
            % (htmlutils.htmlify(branch_name), htmlutils.htmlify(branch_name)),
            is_html=True,
        )

    if not commits:
        raise OperationFailure(
            code="nocommits", title="No commits specified", message="You need at least one commit to create a review."
        )

    commitset = log_commitset.CommitSet(commits)
    heads = commitset.getHeads()

    if len(heads) != 1:
        # There is really no plausible way for this error to occur.
        raise OperationFailure(
            code="disconnectedtree",
            title="Disconnected tree",
            message=(
                "The specified commits do do not form a single connected "
                "tree.  Creating a review of them is not supported."
            ),
        )

    head = heads.pop()

    if len(commitset.getTails()) != 1:
        tail_id = None
    else:
        tail_id = gitutils.Commit.fromSHA1(db, repository, commitset.getTails().pop()).getId(db)

    if not via_push:
        try:
            repository.createBranch(branch_name, head.sha1)
        except gitutils.GitCommandError as error:
            raise OperationFailure(
                code="branchfailed",
                title="Failed to create review branch",
                message=(
                    "<p><b>Output from git:</b></p>"
                    "<code style='padding-left: 1em'>%s</code>" % htmlutils.htmlify(error.output)
                ),
                is_html=True,
            )

    try:
        cursor.execute(
            "INSERT INTO branches (repository, name, head, tail, type) VALUES (%s, %s, %s, %s, 'review') RETURNING id",
            [repository.id, branch_name, head.getId(db), tail_id],
        )

        branch_id = cursor.fetchone()[0]
        reachable_values = [(branch_id, commit.getId(db)) for commit in commits]

        cursor.executemany("INSERT INTO reachable (branch, commit) VALUES (%s, %s)", reachable_values)

        cursor.execute(
            "INSERT INTO reviews (type, branch, state, summary, description, applyfilters, applyparentfilters) VALUES ('official', %s, 'open', %s, %s, %s, %s) RETURNING id",
            (branch_id, summary, description, applyfilters, applyparentfilters),
        )

        review = dbutils.Review.fromId(db, cursor.fetchone()[0])

        cursor.execute("INSERT INTO reviewusers (review, uid, owner) VALUES (%s, %s, TRUE)", (review.id, user.id))

        if reviewfilters is not None:
            cursor.executemany(
                """INSERT INTO reviewfilters (review, uid, path, type, creator)
                                       VALUES (%s, %s, %s, %s, %s)""",
                [
                    (review.id, filter_user_id, filter_path, filter_type, user.id)
                    for filter_user_id, filter_path, filter_type, filter_delegate in reviewfilters
                ],
            )

        is_opt_in = False

        if recipientfilters is not None:
            cursor.executemany(
                "INSERT INTO reviewrecipientfilters (review, uid, include) VALUES (%s, %s, %s)",
                [(review.id, filter_user_id, filter_include) for filter_user_id, filter_include in recipientfilters],
            )

            for filter_user_id, filter_include in recipientfilters:
                if filter_user_id is None and not filter_include:
                    is_opt_in = True

        addCommitsToReview(db, user, review, commits, new_review=True)

        if from_branch_name is not None:
            cursor.execute(
                "UPDATE branches SET review=%s WHERE repository=%s AND name=%s",
                (review.id, repository.id, from_branch_name),
            )

        # Reload to get list of changesets added by addCommitsToReview().
        review = dbutils.Review.fromId(db, review.id)

        pending_mails = []
        recipients = review.getRecipients(db)
        for to_user in recipients:
            pending_mails.extend(mail.sendReviewCreated(db, user, to_user, recipients, review))

            if not is_opt_in and to_user.getPreference(db, "review.defaultOptOut"):
                cursor.execute(
                    "INSERT INTO reviewrecipientfilters (review, uid, include) VALUES (%s, %s, FALSE)",
                    (review.id, to_user.id),
                )

        db.commit()

        mail.sendPendingMails(pending_mails)

        return review
    except:
        if not via_push:
            repository.run("branch", "-D", branch_name)
        raise
Exemple #4
0
def createReview(db,
                 user,
                 repository,
                 commits,
                 branch_name,
                 summary,
                 description,
                 from_branch_name=None,
                 via_push=False,
                 reviewfilters=None,
                 applyfilters=True,
                 applyparentfilters=False,
                 recipientfilters=None):
    cursor = db.cursor()

    if via_push:
        applyparentfilters = bool(
            user.getPreference(db, 'review.applyUpstreamFilters'))

    branch = dbutils.Branch.fromName(db, repository, branch_name)

    if branch is not None:
        raise OperationFailure(
            code="branchexists",
            title="Invalid review branch name",
            message="""\
<p>There is already a branch named <code>%s</code> in the repository.  You have
to select a different name.</p>

<p>If you believe the existing branch was created during an earlier (failed)
attempt to create this review, you can try to delete it from the repository
using the command<p>

<pre>  git push &lt;remote&gt; :%s</pre>

<p>and then press the "Submit Review" button on this page again.""" %
            (htmlutils.htmlify(branch_name), htmlutils.htmlify(branch_name)),
            is_html=True)

    if not commits:
        raise OperationFailure(
            code="nocommits",
            title="No commits specified",
            message="You need at least one commit to create a review.")

    commitset = log_commitset.CommitSet(commits)
    heads = commitset.getHeads()

    if len(heads) != 1:
        # There is really no plausible way for this error to occur.
        raise OperationFailure(
            code="disconnectedtree",
            title="Disconnected tree",
            message=("The specified commits do do not form a single connected "
                     "tree.  Creating a review of them is not supported."))

    head = heads.pop()

    if len(commitset.getTails()) != 1:
        tail_id = None
    else:
        tail_id = gitutils.Commit.fromSHA1(
            db, repository,
            commitset.getTails().pop()).getId(db)

    if not via_push:
        try:
            repository.createBranch(branch_name, head.sha1)
        except gitutils.GitCommandError as error:
            raise OperationFailure(
                code="branchfailed",
                title="Failed to create review branch",
                message=("<p><b>Output from git:</b></p>"
                         "<code style='padding-left: 1em'>%s</code>" %
                         htmlutils.htmlify(error.output)),
                is_html=True)

    createChangesetsForCommits(db, commits)

    try:
        cursor.execute(
            "INSERT INTO branches (repository, name, head, tail, type) VALUES (%s, %s, %s, %s, 'review') RETURNING id",
            [repository.id, branch_name,
             head.getId(db), tail_id])

        branch_id = cursor.fetchone()[0]
        reachable_values = [(branch_id, commit.getId(db))
                            for commit in commits]

        cursor.executemany(
            "INSERT INTO reachable (branch, commit) VALUES (%s, %s)",
            reachable_values)

        cursor.execute(
            "INSERT INTO reviews (type, branch, state, summary, description, applyfilters, applyparentfilters) VALUES ('official', %s, 'open', %s, %s, %s, %s) RETURNING id",
            (branch_id, summary, description, applyfilters,
             applyparentfilters))

        review = dbutils.Review.fromId(db, cursor.fetchone()[0])

        cursor.execute(
            "INSERT INTO reviewusers (review, uid, owner) VALUES (%s, %s, TRUE)",
            (review.id, user.id))

        if reviewfilters is not None:
            cursor.executemany(
                """INSERT INTO reviewfilters (review, uid, path, type, creator)
                                       VALUES (%s, %s, %s, %s, %s)""",
                [(review.id, filter_user_id, filter_path, filter_type, user.id)
                 for filter_user_id, filter_path, filter_type, filter_delegate
                 in reviewfilters])

        is_opt_in = False

        if recipientfilters is not None:
            cursor.executemany(
                "INSERT INTO reviewrecipientfilters (review, uid, include) VALUES (%s, %s, %s)",
                [(review.id, filter_user_id, filter_include)
                 for filter_user_id, filter_include in recipientfilters])

            for filter_user_id, filter_include in recipientfilters:
                if filter_user_id is None and not filter_include:
                    is_opt_in = True

        addCommitsToReview(db, user, review, commits, new_review=True)

        if from_branch_name is not None:
            cursor.execute(
                "UPDATE branches SET review=%s WHERE repository=%s AND name=%s",
                (review.id, repository.id, from_branch_name))

        # Reload to get list of changesets added by addCommitsToReview().
        review = dbutils.Review.fromId(db, review.id)

        pending_mails = []
        recipients = review.getRecipients(db)
        for to_user in recipients:
            pending_mails.extend(
                mail.sendReviewCreated(db, user, to_user, recipients, review))

        if not is_opt_in:
            recipient_by_id = dict(
                (to_user.id, to_user) for to_user in recipients)

            cursor.execute(
                """SELECT userpreferences.uid, userpreferences.repository,
                                     userpreferences.filter, userpreferences.integer
                                FROM userpreferences
                     LEFT OUTER JOIN filters ON (filters.id=userpreferences.filter)
                               WHERE userpreferences.item='review.defaultOptOut'
                                 AND userpreferences.uid=ANY (%s)
                                 AND (userpreferences.filter IS NULL
                                   OR filters.repository=%s)
                                 AND (userpreferences.repository IS NULL
                                   OR userpreferences.repository=%s)""",
                (recipient_by_id.keys(), repository.id, repository.id))

            user_settings = {}
            has_filter_settings = False

            for user_id, repository_id, filter_id, integer in cursor:
                settings = user_settings.setdefault(user_id, [None, None, {}])
                value = bool(integer)

                if repository_id is None and filter_id is None:
                    settings[0] = value
                elif repository_id is not None:
                    settings[1] = value
                else:
                    settings[2][filter_id] = value
                    has_filter_settings = True

            if has_filter_settings:
                filters = Filters()
                filters.setFiles(db, review=review)

            for user_id, (global_default, repository_default,
                          filter_settings) in user_settings.items():
                to_user = recipient_by_id[user_id]
                opt_out = None

                if repository_default is not None:
                    opt_out = repository_default
                elif global_default is not None:
                    opt_out = global_default

                if filter_settings:
                    # Policy:
                    #
                    # If all of the user's filters that matched files in the
                    # review have review.defaultOptOut enabled, then opt out.
                    # When determining this, any review filters of the user's
                    # that match files in the review count as filters that don't
                    # have the review.defaultOptOut enabled.
                    #
                    # If any of the user's filters that matched files in the
                    # review have review.defaultOptOut disabled, then don't opt
                    # out.  When determining this, review filters are ignored.
                    #
                    # Otherwise, ignore the filter settings, and go with either
                    # the user's per-repository or global setting (as set
                    # above.)

                    filters.load(db, review=review, user=to_user)

                    # A set of filter ids.  If None is in the set, the user has
                    # one or more review filters in the review.  (These do not
                    # have ids.)
                    active_filters = filters.getActiveFilters(to_user)

                    for filter_id in active_filters:
                        if filter_id is None:
                            continue
                        elif filter_id in filter_settings:
                            if not filter_settings[filter_id]:
                                opt_out = False
                                break
                        else:
                            break
                    else:
                        if None not in active_filters:
                            opt_out = True

                if opt_out:
                    cursor.execute(
                        """INSERT INTO reviewrecipientfilters (review, uid, include)
                                           VALUES (%s, %s, FALSE)""",
                        (review.id, to_user.id))

        db.commit()

        mail.sendPendingMails(pending_mails)

        return review
    except:
        if not via_push:
            repository.run("branch", "-D", branch_name)
        raise
Exemple #5
0
def createReview(db,
                 user,
                 repository,
                 commits,
                 branch_name,
                 summary,
                 description,
                 from_branch_name=None,
                 via_push=False,
                 reviewfilters=None,
                 applyfilters=True,
                 applyparentfilters=False,
                 recipientfilters=None):
    cursor = db.cursor()

    if via_push:
        applyparentfilters = bool(
            user.getPreference(db, 'review.applyUpstreamFilters'))

    branch = dbutils.Branch.fromName(db, repository, branch_name)

    if branch is not None:
        raise OperationFailure(
            code="branchexists",
            title="Invalid review branch name",
            message="""\
<p>There is already a branch named <code>%s</code> in the repository.  You have
to select a different name.</p>

<p>If you believe the existing branch was created during an earlier (failed)
attempt to create this review, you can try to delete it from the repository
using the command<p>

<pre>  git push &lt;remote&gt; :%s</pre>

<p>and then press the "Submit Review" button on this page again.""" %
            (htmlutils.htmlify(branch_name), htmlutils.htmlify(branch_name)),
            is_html=True)

    commitset = log_commitset.CommitSet(commits)

    if len(commitset.getHeads()) != 1:
        raise Exception, "invalid commit-set; multiple heads"

    head = commitset.getHeads().pop()

    if len(commitset.getTails()) != 1:
        tail_id = None
    else:
        tail_id = gitutils.Commit.fromSHA1(
            db, repository,
            commitset.getTails().pop()).getId(db)

    if not via_push:
        repository.branch(branch_name, head.sha1)

    try:
        cursor.execute(
            "INSERT INTO branches (repository, name, head, tail, type) VALUES (%s, %s, %s, %s, 'review') RETURNING id",
            [repository.id, branch_name,
             head.getId(db), tail_id])

        branch_id = cursor.fetchone()[0]
        reachable_values = [(branch_id, commit.getId(db))
                            for commit in commits]

        cursor.executemany(
            "INSERT INTO reachable (branch, commit) VALUES (%s, %s)",
            reachable_values)

        cursor.execute(
            "INSERT INTO reviews (type, branch, state, summary, description, applyfilters, applyparentfilters) VALUES ('official', %s, 'open', %s, %s, %s, %s) RETURNING id",
            (branch_id, summary, description, applyfilters,
             applyparentfilters))

        review = dbutils.Review.fromId(db, cursor.fetchone()[0])

        cursor.execute(
            "INSERT INTO reviewusers (review, uid, owner) VALUES (%s, %s, TRUE)",
            (review.id, user.id))

        if reviewfilters is not None:
            cursor.executemany(
                "INSERT INTO reviewfilters (review, uid, directory, file, type, creator) VALUES (%s, %s, %s, %s, %s, %s)",
                [(review.id, filter_user_id, filter_directory_id,
                  filter_file_id, filter_type, user.id)
                 for filter_directory_id, filter_file_id, filter_type,
                 filter_delegate, filter_user_id in reviewfilters])

        if recipientfilters is not None:
            cursor.executemany(
                "INSERT INTO reviewrecipientfilters (review, uid, include) VALUES (%s, %s, %s)",
                [(review.id, filter_user_id, filter_include)
                 for filter_user_id, filter_include in recipientfilters])

        addCommitsToReview(db, user, review, commits, new_review=True)

        if from_branch_name is not None:
            cursor.execute(
                "UPDATE branches SET review=%s WHERE repository=%s AND name=%s",
                (review.id, repository.id, from_branch_name))

        # Reload to get list of changesets added by addCommitsToReview().
        review = dbutils.Review.fromId(db, review.id)

        pending_mails = []
        recipients = review.getRecipients(db)
        for to_user in recipients:
            pending_mails.extend(
                mail.sendReviewCreated(db, user, to_user, recipients, review))

        db.commit()

        mail.sendPendingMails(pending_mails)

        return review
    except:
        if not via_push:
            repository.run("branch", "-D", branch_name)
        raise