django-triager-bot / djangotriager / trac /

from subprocess import Popen, PIPE

class Patch(object):
    """A class to help working with patches.

    You can use it to apply a patch on a directory, retrieve all files in 
    the patch or the files that failed to apply. To use it, you just need
    to supply the patch content.
    VALID_EXTENSIONS = ("diff", "patch")

    def __init__(self, patch_id, content):
        self._patch_id = patch_id
        self._content = content

    def __repr__(self):
        return "<Patch %r>" % self._patch_id

    def validate(self, filename):
        # FIXME: don't try to guess file type through its extension
        parts = filename.rsplit(".", 1)
        return len(parts) == 2 and parts[1] in Patch.VALID_EXTENSIONS

    def apply(self, where, prefix=0, logger=None):
        proc = Popen(["patch", "-p%d" % prefix, "-f"], cwd=where, stdin=PIPE,
                     stdout=PIPE, stderr=PIPE)
        stdout, stderr = proc.communicate(self._content)
        if proc.returncode != 0:
            if logger:
      "Patch could not be applied with prefix=%r" % prefix)
            if prefix < Patch.MAX_APPLY_ATTEMPTS:
                return self.apply(where, prefix=prefix + 1, logger=logger)
                return False
  "Patch applied successfully")
        return True