diff options
| -rw-r--r-- | meta/lib/oe/patch.py | 86 | 
1 files changed, 86 insertions, 0 deletions
| diff --git a/meta/lib/oe/patch.py b/meta/lib/oe/patch.py index 788f465bd9..2d56ba404e 100644 --- a/meta/lib/oe/patch.py +++ b/meta/lib/oe/patch.py @@ -202,6 +202,78 @@ class GitApplyTree(PatchTree):      def __init__(self, dir, d):          PatchTree.__init__(self, dir, d) +    @staticmethod +    def extractPatchHeader(patchfile): +        """ +        Extract just the header lines from the top of a patch file +        """ +        lines = [] +        with open(patchfile, 'r') as f: +            for line in f.readlines(): +                if line.startswith('Index: ') or line.startswith('diff -') or line.startswith('---'): +                    break +                lines.append(line) +        return lines + +    @staticmethod +    def prepareCommit(patchfile): +        """ +        Prepare a git commit command line based on the header from a patch file +        (typically this is useful for patches that cannot be applied with "git am" due to formatting) +        """ +        import tempfile +        import re +        author_re = re.compile('[\S ]+ <\S+@\S+\.\S+>') +        # Process patch header and extract useful information +        lines = GitApplyTree.extractPatchHeader(patchfile) +        outlines = [] +        author = None +        date = None +        for line in lines: +            if line.startswith('Subject: '): +                subject = line.split(':', 1)[1] +                # Remove any [PATCH][oe-core] etc. +                subject = re.sub(r'\[.+?\]\s*', '', subject) +                outlines.insert(0, '%s\n\n' % subject.strip()) +                continue +            if line.startswith('From: ') or line.startswith('Author: '): +                authorval = line.split(':', 1)[1].strip().replace('"', '') +                # git is fussy about author formatting i.e. it must be Name <email@domain> +                if author_re.match(authorval): +                    author = authorval +                    continue +            if line.startswith('Date: '): +                if date is None: +                    dateval = line.split(':', 1)[1].strip() +                    # Very crude check for date format, since git will blow up if it's not in the right +                    # format. Without e.g. a python-dateutils dependency we can't do a whole lot more +                    if len(dateval) > 12: +                        date = dateval +                continue +            if line.startswith('Signed-off-by: '): +                authorval = line.split(':', 1)[1].strip().replace('"', '') +                # git is fussy about author formatting i.e. it must be Name <email@domain> +                if author_re.match(authorval): +                    author = authorval +            outlines.append(line) +        # Add a pointer to the original patch file name +        if outlines and outlines[-1].strip(): +            outlines.append('\n') +        outlines.append('(from original patch: %s)\n' % os.path.basename(patchfile)) +        # Write out commit message to a file +        with tempfile.NamedTemporaryFile('w', delete=False) as tf: +            tmpfile = tf.name +            for line in outlines: +                tf.write(line) +        # Prepare git command +        cmd = ["git", "commit", "-F", tmpfile] +        # git doesn't like plain email addresses as authors +        if author and '<' in author: +            cmd.append('--author="%s"' % author) +        if date: +            cmd.append('--date="%s"' % date) +        return (tmpfile, cmd) +      def _applypatch(self, patch, force = False, reverse = False, run = True):          def _applypatchhelper(shellcmd, patch, force = False, reverse = False, run = True):              if reverse: @@ -218,11 +290,25 @@ class GitApplyTree(PatchTree):              shellcmd = ["git", "--work-tree=.", "am", "-3", "-p%s" % patch['strippath']]              return _applypatchhelper(shellcmd, patch, force, reverse, run)          except CmdError: +            # Fall back to git apply              shellcmd = ["git", "--git-dir=.", "apply", "-p%s" % patch['strippath']]              try:                  output = _applypatchhelper(shellcmd, patch, force, reverse, run)              except CmdError: +                # Fall back to patch                  output = PatchTree._applypatch(self, patch, force, reverse, run) +            # Add all files +            shellcmd = ["git", "add", "-f", "."] +            output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir) +            # Exclude the patches directory +            shellcmd = ["git", "reset", "HEAD", self.patchdir] +            output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir) +            # Commit the result +            (tmpfile, shellcmd) = self.prepareCommit(patch['file']) +            try: +                output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir) +            finally: +                os.remove(tmpfile)              return output | 
