django-triager-bot / djangotriager / trac / tickets.py

from djangotriager.trac.server import get_proxy
from djangotriager.trac.patches import Patch
from djangotriager.wc.subversion import Subversion
from djangotriager.tests import TestRunner
from djangotriager.reporter import Reporter

class Ticket(object):
    """
    Class representing a SCM ticket.
    """
    def __init__(self, ticket_id):
        self._ticket_id = int(ticket_id)
        self.__patches = []
        self._reporter = Reporter("Ticket #%d" % self._ticket_id)

    def get_report(self):
        """Print the report generated so far.

        You can use this to retrieve the report instead of sending to the
        ticket's page at the SCM instance.
        """
        return self._reporter.get_buffer()

    @classmethod
    def get_by_query(cls, config, query):
        """
        Retrieve all tickets that matches the query string given.
        """
        proxy = get_proxy(config.get("trac"))
        return [cls(ticket_id) for ticket_id in proxy.ticket.query(query)]

    def get_patches(self, config):
        """
        Return all patches available for the ticket.
        """
        if not self.__patches:
            proxy = get_proxy(config.get("trac"))
            attachments = proxy.ticket.listAttachments(self._ticket_id)
            self.__patches = [Patch(config, self._ticket_id, file[0]) 
                                  for file in attachments 
                                      if Patch.validate(file[0])]
            self._reporter.warn("Patches retrieved: %r" % self.__patches)
        return self.__patches

    def try_patch(self, config, patch):
        """Check if the given patch is valid.

        The patch is applied in the working copy and validate through the test
        suite, after this the changes in the working copy is reverted.
        """
        working_copy = Subversion(dir=config.get("working_copy"))
        self._reporter.warn("Cleaning working copy")
        working_copy.revert_changes()
        self._reporter.warn("Trying patch %r" % patch)
        self._reporter.warn("Applying patch")
        is_valid = False
        if not patch.apply(working_copy.dir, logger=self._reporter):
            self._reporter.warn("Patch %r could not be applied..." % patch)
        else:
            self._reporter.warn("Running tests")
            is_valid = TestRunner(working_copy).run(logger=self._reporter)
        self._reporter.warn("Restoring working copy")
        working_copy.revert_changes()
        return is_valid

    def try_patches(self, config, limit=None):
        patches = self.get_patches(config)
        if not patches:
            self._reporter.warn("No patch to process")
        else:
            for idx, patch in enumerate(reversed(patches)):
                self.try_patch(config, patch)
                if limit and idx == limit - 1:
                    self._reporter.warn("Limit of patches (%d) reached, "
                                        "finishing" % limit)
                    break
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.