Esempio n. 1
0
def addNote(req, db, user):
    repository_id = req.getParameter("repository", filter=int)
    branch = req.getParameter("branch")
    upstream = req.getParameter("upstream")
    sha1 = req.getParameter("sha1")
    review_id = req.getParameter("review", None)
    text = req.read().strip()

    if review_id is not None:
        review = dbutils.Review.fromId(db, review_id)
    else:
        review = None

    cursor = db.cursor()
    cursor.execute("DELETE FROM checkbranchnotes WHERE repository=%s AND branch=%s AND upstream=%s AND sha1=%s",
                   (repository_id, branch, upstream, sha1))
    cursor.execute("INSERT INTO checkbranchnotes (repository, branch, upstream, sha1, uid, review, text) VALUES (%s, %s, %s, %s, %s, %s, %s)",
                   (repository_id, branch, upstream, sha1, user.id, review_id, text or None))
    db.commit()

    response = "ok"

    if review and review.repository.id == repository_id:
        repository = gitutils.Repository.fromId(db, repository_id)
        commit = gitutils.Commit.fromSHA1(db, repository, sha1)
        commitset = log.commitset.CommitSet(review.branch.getCommits(db))

        upstreams = commitset.getFilteredTails(repository)
        if len(upstreams) == 1:
            upstream = upstreams.pop()
            if repository.mergebase([commit.sha1, upstream]) == upstream:
                response = "rebase"

    return response
Esempio n. 2
0
def addNote(req, db, user):
    repository_id = req.getParameter("repository", filter=int)
    branch = req.getParameter("branch")
    upstream = req.getParameter("upstream")
    sha1 = req.getParameter("sha1")
    review_id = req.getParameter("review", None)
    text = req.read().strip()

    if review_id is not None:
        review = dbutils.Review.fromId(db, review_id)
    else:
        review = None

    cursor = db.cursor()
    cursor.execute("DELETE FROM checkbranchnotes WHERE repository=%s AND branch=%s AND upstream=%s AND sha1=%s",
                   (repository_id, branch, upstream, sha1))
    cursor.execute("INSERT INTO checkbranchnotes (repository, branch, upstream, sha1, uid, review, text) VALUES (%s, %s, %s, %s, %s, %s, %s)",
                   (repository_id, branch, upstream, sha1, user.id, review_id, text or None))
    db.commit()

    response = "ok"

    if review and review.repository.id == repository_id:
        repository = gitutils.Repository.fromId(db, repository_id)
        commit = gitutils.Commit.fromSHA1(db, repository, sha1)
        commitset = log.commitset.CommitSet(review.branch.commits)

        upstreams = commitset.getFilteredTails(repository)
        if len(upstreams) == 1:
            upstream = upstreams.pop()
            if repository.mergebase([commit.sha1, upstream]) == upstream:
                response = "rebase"

    return response
Esempio n. 3
0
    def process(self, db, user, review_id, new_head_sha1, new_upstream_sha1=None, branch=None, new_trackedbranch=None):
        review = dbutils.Review.fromId(db, review_id)
        new_head = gitutils.Commit.fromSHA1(db, review.repository, new_head_sha1)

        cursor = db.cursor()

        if review.state == 'closed':
            cursor.execute("SELECT closed_by FROM reviews WHERE id=%s", (review.id,))
            closed_by = cursor.fetchone()[0]

            review.serial += 1
            cursor.execute("UPDATE reviews SET state='open', serial=%s, closed_by=NULL WHERE id=%s", (review.serial, review.id))
        else:
            closed_by = None

        trackedbranch = review.getTrackedBranch(db)
        if trackedbranch and not trackedbranch.disabled:
            cursor.execute("UPDATE trackedbranches SET disabled=TRUE WHERE id=%s", (trackedbranch.id,))

        commitset = log.commitset.CommitSet(review.branch.commits)
        tails = commitset.getFilteredTails(review.branch.repository)

        if len(tails) == 1 and tails.pop() == new_upstream_sha1:
            # This appears to be a history rewrite.
            new_upstream_sha1 = None

        doPrepareRebase(db, user, review, new_upstream_sha1, branch)

        try:
            review.repository.run("update-ref", "refs/commit/%s" % new_head.sha1, new_head.sha1)

            with review.repository.relaycopy("RebaseReview") as relay:
                relay.run("fetch", "origin", "refs/commit/%s" % new_head.sha1)
                relay.run("push", "--force", "origin",
                          "%s:refs/heads/%s" % (new_head.sha1, review.branch.name),
                          env={ "REMOTE_USER": user.name })

            if closed_by is not None:
                db.commit()
                state = review.getReviewState(db)
                if state.accepted:
                    review.serial += 1
                    cursor.execute("UPDATE reviews SET state='closed', serial=%s, closed_by=%s WHERE id=%s", (review.serial, closed_by, review.id))

            if trackedbranch and not trackedbranch.disabled:
                cursor.execute("UPDATE trackedbranches SET disabled=FALSE WHERE id=%s", (trackedbranch.id,))
            if new_trackedbranch:
                cursor.execute("UPDATE trackedbranches SET remote_name=%s WHERE id=%s", (new_trackedbranch, trackedbranch.id))

            db.commit()
        except:
            doCancelRebase(db, user, review)
            raise

        return OperationResult()
Esempio n. 4
0
    def process(self, db, user, review_id, new_head_sha1, new_upstream_sha1=None, branch=None, new_trackedbranch=None):
        review = dbutils.Review.fromId(db, review_id)
        new_head = gitutils.Commit.fromSHA1(db, review.repository, new_head_sha1)

        cursor = db.cursor()

        if review.state == 'closed':
            cursor.execute("SELECT closed_by FROM reviews WHERE id=%s", (review.id,))
            closed_by = cursor.fetchone()[0]

            review.serial += 1
            cursor.execute("UPDATE reviews SET state='open', serial=%s, closed_by=NULL WHERE id=%s", (review.serial, review.id))
        else:
            closed_by = None

        trackedbranch = review.getTrackedBranch(db)
        if trackedbranch and not trackedbranch.disabled:
            cursor.execute("UPDATE trackedbranches SET disabled=TRUE WHERE id=%s", (trackedbranch.id,))

        commitset = log.commitset.CommitSet(review.branch.commits)
        tails = commitset.getFilteredTails(review.branch.repository)

        if len(tails) == 1 and tails.pop() == new_upstream_sha1:
            # This appears to be a history rewrite.
            new_upstream_sha1 = None

        doPrepareRebase(db, user, review, new_upstream_sha1, branch)

        try:
            with review.repository.relaycopy("RebaseReview") as relay:
                with review.repository.temporaryref(new_head) as ref_name:
                    relay.run("fetch", "origin", ref_name)
                relay.run("push", "--force", "origin",
                          "%s:refs/heads/%s" % (new_head.sha1, review.branch.name),
                          env={ "REMOTE_USER": user.name })

            if closed_by is not None:
                db.commit()
                state = review.getReviewState(db)
                if state.accepted:
                    review.serial += 1
                    cursor.execute("UPDATE reviews SET state='closed', serial=%s, closed_by=%s WHERE id=%s", (review.serial, closed_by, review.id))

            if trackedbranch and not trackedbranch.disabled:
                cursor.execute("UPDATE trackedbranches SET disabled=FALSE WHERE id=%s", (trackedbranch.id,))
            if new_trackedbranch:
                cursor.execute("UPDATE trackedbranches SET remote_name=%s WHERE id=%s", (new_trackedbranch, trackedbranch.id))

            db.commit()
        except:
            doCancelRebase(db, user, review)
            raise

        return OperationResult()
Esempio n. 5
0
def doPrepareRebase(db, user, review, new_upstream_arg=None, branch=None):
    commitset = log.commitset.CommitSet(review.branch.commits)
    tails = commitset.getFilteredTails(review.branch.repository)

    cursor = db.cursor()

    cursor.execute("SELECT uid FROM reviewrebases WHERE review=%s AND new_head IS NULL", (review.id,))
    row = cursor.fetchone()
    if row:
        rebaser = dbutils.User.fromId(db, row[0])
        raise OperationError("The review is already being rebased by %s <%s>." % (rebaser.fullname, rebaser.email))

    head = commitset.getHeads().pop()
    head_id = head.getId(db)

    if new_upstream_arg is not None:
        if len(tails) > 1:
            raise OperationError("Rebase to new upstream commit not supported.")

        tail = gitutils.Commit.fromSHA1(db, review.branch.repository, tails.pop())

        old_upstream_id = tail.getId(db)
        if new_upstream_arg == "0" * 40:
            new_upstream_id = None
        else:
            if not gitutils.re_sha1.match(new_upstream_arg):
                cursor.execute("SELECT sha1 FROM tags WHERE repository=%s AND name=%s", (review.branch.repository.id, new_upstream_arg))
                row = cursor.fetchone()
                if row: new_upstream_arg = row[0]
                else: raise OperationError("Specified new upstream is invalid.")

            try: new_upstream = gitutils.Commit.fromSHA1(db, review.branch.repository, new_upstream_arg)
            except: raise OperationError("The specified new upstream commit does not exist in Critic's repository.")

            new_upstream_id = new_upstream.getId(db)
    else:
        old_upstream_id = None
        new_upstream_id = None

    cursor.execute("""INSERT INTO reviewrebases (review, old_head, new_head, old_upstream, new_upstream, uid, branch)
                           VALUES (%s, %s, NULL, %s, %s, %s, %s)""",
                   (review.id, head_id, old_upstream_id, new_upstream_id, user.id, branch))

    review.incrementSerial(db)

    db.commit()
Esempio n. 6
0
def doPrepareRebase(db, user, review, new_upstream_arg=None, branch=None):
    commitset = log.commitset.CommitSet(review.branch.commits)
    tails = commitset.getFilteredTails(review.branch.repository)

    cursor = db.cursor()

    cursor.execute("SELECT uid FROM reviewrebases WHERE review=%s AND new_head IS NULL", (review.id,))
    row = cursor.fetchone()
    if row:
        rebaser = dbutils.User.fromId(db, row[0])
        raise OperationError("The review is already being rebased by %s <%s>." % (rebaser.fullname, rebaser.email))

    head = commitset.getHeads().pop()
    head_id = head.getId(db)

    if new_upstream_arg is not None:
        if len(tails) > 1:
            raise OperationError("Rebase to new upstream commit not supported.")

        tail = gitutils.Commit.fromSHA1(db, review.branch.repository, tails.pop())

        old_upstream_id = tail.getId(db)
        if new_upstream_arg == "0" * 40:
            new_upstream_id = None
        else:
            if not gitutils.re_sha1.match(new_upstream_arg):
                cursor.execute("SELECT sha1 FROM tags WHERE repository=%s AND name=%s", (review.branch.repository.id, new_upstream_arg))
                row = cursor.fetchone()
                if row: new_upstream_arg = row[0]
                else: raise OperationError("Specified new upstream is invalid.")

            try: new_upstream = gitutils.Commit.fromSHA1(db, review.branch.repository, new_upstream_arg)
            except: raise OperationError("The specified new upstream commit does not exist in Critic's repository.")

            new_upstream_id = new_upstream.getId(db)
    else:
        old_upstream_id = None
        new_upstream_id = None

    cursor.execute("""INSERT INTO reviewrebases (review, old_head, new_head, old_upstream, new_upstream, uid, branch)
                           VALUES (%s, %s, NULL, %s, %s, %s, %s)""",
                   (review.id, head_id, old_upstream_id, new_upstream_id, user.id, branch))

    review.incrementSerial(db)

    db.commit()
Esempio n. 7
0
 def getFilteredTails(self):
     import log.commitset
     commitset = log.commitset.CommitSet(self.branch.commits)
     return commitset.getFilteredTails(self.branch.repository)
Esempio n. 8
0
def execute(db, user, review, all_commits, old_head, new_head, output):
    cursor = db.cursor()

    installs = Extension.getInstalls(db, user)

    data = None

    for extension_id, version_id, version_sha1, is_universal in installs:
        handlers = []

        extension = Extension.fromId(db, extension_id)

        if version_id is not None:
            cursor.execute("""SELECT script, function
                                FROM extensionroles
                                JOIN extensionprocesscommitsroles ON (role=id)
                               WHERE version=%s
                            ORDER BY id ASC""",
                           (version_id,))

            handlers.extend(cursor)

            if not handlers:
                continue

            extension_path = getExtensionInstallPath(version_sha1)
            manifest = Manifest.load(extension_path)
        else:
            manifest = Manifest.load(extension.getPath())

            for role in manifest.roles:
                if isinstance(role, ProcessCommitsRole):
                    handlers.append((role.script, role.function))

            if not handlers:
                continue

        if data is None:
            commitset = log.commitset.CommitSet(all_commits)

            assert old_head is None or old_head in commitset.getTails()
            assert new_head in commitset.getHeads()
            assert len(commitset.getHeads()) == 1

            tails = commitset.getFilteredTails(review.repository)
            if len(tails) == 1:
                tail = gitutils.Commit.fromSHA1(db, review.repository, tails.pop())
                changeset_id = changeset.utils.createChangeset(
                    db, user, review.repository, from_commit=tail, to_commit=new_head)[0].id
                changeset_arg = "repository.getChangeset(%d)" % changeset_id
            else:
                changeset_arg = "null"

            commits_arg = "[%s]" % ",".join(
                [("repository.getCommit(%d)" % commit.getId(db))
                 for commit in all_commits])

            data = { "review_id": review.id,
                     "changeset": changeset_arg,
                     "commits": commits_arg }

        for script, function in handlers:
            class Error(Exception):
                pass

            def print_header():
                header = "%s::%s()" % (script, function)
                print >>output, ("\n[%s] %s\n[%s] %s"
                                 % (extension.getName(), header,
                                    extension.getName(), "=" * len(header)))

            try:
                argv = """

(function ()
 {
   var review = new critic.Review(%(review_id)d);
   var repository = review.repository;
   var changeset = %(changeset)s;
   var commitset = new critic.CommitSet(%(commits)s);

   return [review, changeset, commitset];
 })()

""" % data
                argv = re.sub("[ \n]+", " ", argv.strip())

                try:
                    stdout_data = executeProcess(
                        manifest, "processcommits", script, function, extension_id, user.id,
                        argv, configuration.extensions.SHORT_TIMEOUT)
                except ProcessTimeout:
                    raise Error("Timeout after %d seconds." % configuration.extensions.SHORT_TIMEOUT)
                except ProcessError as error:
                    if error.returncode < 0:
                        raise Error("Process terminated by signal %d." % -error.returncode)
                    else:
                        raise Error("Process returned %d.\n%s" % (error.returncode, error.stderr))

                if stdout_data.strip():
                    print_header()
                    for line in stdout_data.splitlines():
                        print >>output, "[%s] %s" % (extension.getName(), line)
            except Error as error:
                print_header()
                print >>output, "[%s] Extension error: %s" % (extension.getName(), error.message)
Esempio n. 9
0
def execute(db, user, review, all_commits, old_head, new_head, output):
    cursor = db.cursor()

    installs = Extension.getInstalls(db, user)

    data = None

    for extension_id, version_id, version_sha1, is_universal in installs:
        handlers = []

        extension = Extension.fromId(db, extension_id)

        if version_id is not None:
            cursor.execute(
                """SELECT script, function
                                FROM extensionroles
                                JOIN extensionprocesscommitsroles ON (role=id)
                               WHERE version=%s
                            ORDER BY id ASC""", (version_id, ))

            handlers.extend(cursor)

            if not handlers:
                continue

            extension_path = getExtensionInstallPath(version_sha1)
            manifest = Manifest.load(extension_path)
        else:
            manifest = Manifest.load(extension.getPath())

            for role in manifest.roles:
                if isinstance(role, ProcessCommitsRole):
                    handlers.append((role.script, role.function))

            if not handlers:
                continue

        if data is None:
            commitset = log.commitset.CommitSet(all_commits)

            assert old_head is None or old_head in commitset.getTails()
            assert new_head in commitset.getHeads()
            assert len(commitset.getHeads()) == 1

            tails = commitset.getFilteredTails(review.repository)
            if len(tails) == 1:
                tail = gitutils.Commit.fromSHA1(db, review.repository,
                                                tails.pop())
                changeset_id = changeset.utils.createChangeset(
                    db,
                    user,
                    review.repository,
                    from_commit=tail,
                    to_commit=new_head)[0].id
                changeset_arg = "repository.getChangeset(%d)" % changeset_id
            else:
                changeset_arg = "null"

            commits_arg = "[%s]" % ",".join(
                [("repository.getCommit(%d)" % commit.getId(db))
                 for commit in all_commits])

            data = {
                "review_id": review.id,
                "changeset": changeset_arg,
                "commits": commits_arg
            }

        for script, function in handlers:

            class Error(Exception):
                pass

            def print_header():
                header = "%s::%s()" % (script, function)
                print >> output, ("\n[%s] %s\n[%s] %s" %
                                  (extension.getName(), header,
                                   extension.getName(), "=" * len(header)))

            try:
                argv = """

(function ()
 {
   var review = new critic.Review(%(review_id)d);
   var repository = review.repository;
   var changeset = %(changeset)s;
   var commitset = new critic.CommitSet(%(commits)s);

   return [review, changeset, commitset];
 })()

""" % data
                argv = re.sub("[ \n]+", " ", argv.strip())

                try:
                    stdout_data = executeProcess(
                        manifest, "processcommits", script, function,
                        extension_id, user.id, argv,
                        configuration.extensions.SHORT_TIMEOUT)
                except ProcessTimeout:
                    raise Error("Timeout after %d seconds." %
                                configuration.extensions.SHORT_TIMEOUT)
                except ProcessError as error:
                    if error.returncode < 0:
                        raise Error("Process terminated by signal %d." %
                                    -error.returncode)
                    else:
                        raise Error("Process returned %d.\n%s" %
                                    (error.returncode, error.stderr))

                if stdout_data.strip():
                    print_header()
                    for line in stdout_data.splitlines():
                        print >> output, "[%s] %s" % (extension.getName(),
                                                      line)
            except Error as error:
                print_header()
                print >> output, "[%s] Extension error: %s" % (
                    extension.getName(), error.message)
Esempio n. 10
0
 def getFilteredTails(self, db):
     import log.commitset
     commitset = log.commitset.CommitSet(self.branch.getCommits(db))
     return commitset.getFilteredTails(self.branch.repository)
Esempio n. 11
0
def execute(db, user, review, all_commits, old_head, new_head, output):
    cursor = db.cursor()
    cursor.execute("""SELECT extensions.id, extensions.author, extensions.name, extensionversions.sha1, roles.script, roles.function
                        FROM extensions
                        JOIN extensionversions ON (extensionversions.extension=extensions.id)
                        JOIN extensionroles_processcommits AS roles ON (roles.version=extensionversions.id)
                       WHERE uid=%s
                         AND filter IS NULL""", (user.id,))

    rows = cursor.fetchall()

    if rows:
        commitset = log.commitset.CommitSet(all_commits)

        assert old_head is None or old_head in commitset.getTails()
        assert new_head in commitset.getHeads()
        assert len(commitset.getHeads()) == 1

        tails = commitset.getFilteredTails(review.repository)
        if len(tails) == 1:
            tail = gitutils.Commit.fromSHA1(db, review.repository, tails.pop())
            changeset_id = changeset.utils.createChangeset(db, user, review.repository, from_commit=tail, to_commit=new_head)[0].id
            changeset_arg = "repository.getChangeset(%d)" % changeset_id
            db.commit()
        else:
            changeset_arg = "null"

        commits = "[%s]" % ",".join([("repository.getCommit(%d)" % commit.getId(db)) for commit in all_commits])

        data = { "review_id": review.id,
                 "changeset": changeset_arg,
                 "commits": commits }

        for extension_id, author_id, extension_name, sha1, script, function in rows:
            author = dbutils.User.fromId(db, author_id)

            if sha1 is None: extension_path = getExtensionPath(author.name, extension_name)
            else: extension_path = getExtensionInstallPath(sha1)

            class Error(Exception):
                pass

            def print_header():
                header = "%s::%s()" % (script, function)
                print >>output, "\n[%s] %s\n[%s] %s" % (extension_name, header, extension_name, "=" * len(header))

            try:
                try:
                    manifest = Manifest.load(extension_path)
                except ManifestError, error:
                    raise Error("Invalid MANIFEST:\n%s" % error.message)

                for role in manifest.roles:
                    if isinstance(role, ProcessCommitsRole) and role.script == script and role.function == function:
                        break
                else:
                    continue

                argv = """

(function ()
 {
   var review = new critic.Review(%(review_id)d);
   var repository = review.repository;
   var changeset = %(changeset)s;
   var commitset = new critic.CommitSet(%(commits)s);

   return [review, changeset, commitset];
 })()

""" % data
                argv = re.sub("[ \n]+", " ", argv.strip())

                try:
                    stdout_data = executeProcess(manifest, role, extension_id, user.id, argv, configuration.extensions.SHORT_TIMEOUT)
                except ProcessTimeout:
                    raise Error("Timeout after %d seconds." % configuration.extensions.SHORT_TIMEOUT)
                except ProcessError, error:
                    if error.returncode < 0:
                        if -error.returncode == signal.SIGXCPU:
                            raise Error("CPU time limit (5 seconds) exceeded.")
                        else:
                            raise Error("Process terminated by signal %d." % -error.returncode)
                    else:
                        raise Error("Process returned %d.\n%s" % (error.returncode, error.stderr))

                if stdout_data.strip():
                    print_header()
                    for line in stdout_data.splitlines():
                        print >>output, "[%s] %s" % (extension_name, line)
            except Error, error:
                print_header()
                print >>output, "[%s] Extension error: %s" % (extension_name, error.message)