Update drivers
[vuplus_openembedded] / classes / patch.bbclass
index ea01824..33184df 100644 (file)
@@ -1,13 +1,30 @@
 # Copyright (C) 2006  OpenedHand LTD
 
+# Point to an empty file so any user's custom settings don't break things
+QUILTRCFILE ?= "${STAGING_BINDIR_NATIVE}/quiltrc"
+
 def patch_init(d):
-       import os, sys
+       class NotFoundError(Exception):
+               def __init__(self, path):
+                       self.path = path
+               def __str__(self):
+                       return "Error: %s not found." % self.path
 
        def md5sum(fname):
-               import md5, sys
+               # when we move to Python 2.5 as minimal supported
+               # we can kill that try/except as hashlib is 2.5+
+               try:
+                       import hashlib
+                       m = hashlib.md5()
+               except ImportError:
+                       import md5
+                       m = md5.new()
+
+               try:
+                       f = file(fname, 'rb')
+               except IOError:
+                       raise NotFoundError(fname)
 
-               f = file(fname, 'rb')
-               m = md5.new()
                while True:
                        d = f.read(8096)
                        if not d:
@@ -24,11 +41,6 @@ def patch_init(d):
                def __str__(self):
                        return "Command Error: exit status: %d  Output:\n%s" % (self.status, self.output)
 
-       class NotFoundError(Exception):
-               def __init__(self, path):
-                       self.path = path
-               def __str__(self):
-                       return "Error: %s not found." % self.path
 
        def runcmd(args, dir = None):
                import commands
@@ -38,7 +50,7 @@ def patch_init(d):
                        if not os.path.exists(dir):
                                raise NotFoundError(dir)
                        os.chdir(dir)
-                       # print("cwd: %s -> %s" % (olddir, self.dir))
+                       # print("cwd: %s -> %s" % (olddir, dir))
 
                try:
                        args = [ commands.mkarg(str(arg)) for arg in args ]
@@ -60,8 +72,6 @@ def patch_init(d):
                def __str__(self):
                        return "Patch Error: %s" % self.msg
 
-       import bb, bb.data, bb.fetch
-
        class PatchSet(object):
                defaults = {
                        "strippath": 1
@@ -117,40 +127,50 @@ def patch_init(d):
                        """"""
                        PatchSet.Import(self, patch, force)
 
-                       self.patches.insert(self._current or 0, patch)
+                       if self._current is not None:
+                               i = self._current + 1
+                       else:
+                               i = 0
+                       self.patches.insert(i, patch)
 
-               def _applypatch(self, patch, force = None, reverse = None):
-                       shellcmd = ["patch", "<", patch['file'], "-p", patch['strippath']]
+               def _applypatch(self, patch, force = False, reverse = False, run = True):
+                       shellcmd = ["cat", patch['file'], "|", "patch", "-p", patch['strippath']]
                        if reverse:
                                shellcmd.append('-R')
-                       shellcmd.append('--dry-run')
 
-                       try:
-                               output = runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
-                       except CmdError:
-                               if force:
-                                       shellcmd.pop(len(shellcmd) - 1)
-                                       output = runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
-                               else:
-                                       import sys
-                                       raise sys.exc_value
+                       if not run:
+                               return "sh" + "-c" + " ".join(shellcmd)
+
+                       if not force:
+                               shellcmd.append('--dry-run')
 
+                       output = runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
+
+                       if force:
+                               return
+
+                       shellcmd.pop(len(shellcmd) - 1)
+                       output = runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
                        return output
 
-               def Push(self, force = None, all = None):
+               def Push(self, force = False, all = False, run = True):
+                       bb.note("self._current is %s" % self._current)
+                       bb.note("patches is %s" % self.patches)
                        if all:
                                for i in self.patches:
                                        if self._current is not None:
                                                self._current = self._current + 1
                                        else:
                                                self._current = 0
+                                       bb.note("applying patch %s" % i)
                                        self._applypatch(i, force)
                        else:
                                if self._current is not None:
                                        self._current = self._current + 1
                                else:
                                        self._current = 0
-                               self._applypatch(self.patches[self._current], force)
+                               bb.note("applying patch %s" % self.patches[self._current])
+                               return self._applypatch(self.patches[self._current], force)
 
 
                def Pop(self, force = None, all = None):
@@ -163,9 +183,30 @@ def patch_init(d):
                def Clean(self):
                        """"""
 
+       class GitApplyTree(PatchTree):
+               def __init__(self, dir, d):
+                       PatchTree.__init__(self, dir, d)
+
+               def _applypatch(self, patch, force = False, reverse = False, run = True):
+                       shellcmd = ["git", "--git-dir=.", "apply", "-p%s" % patch['strippath']]
+
+                       if reverse:
+                               shellcmd.append('-R')
+
+                       shellcmd.append(patch['file'])
+
+                       if not run:
+                               return "sh" + "-c" + " ".join(shellcmd)
+
+                       return runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
+
+
        class QuiltTree(PatchSet):
-               def _runcmd(self, args):
-                       runcmd(["quilt"] + args, self.dir)
+               def _runcmd(self, args, run = True):
+                       quiltrc = bb.data.getVar('QUILTRCFILE', self.d, 1)
+                       if not run:
+                               return ["quilt"] + ["--quiltrc"] + [quiltrc] + args
+                       runcmd(["quilt"] + ["--quiltrc"] + [quiltrc] + args, self.dir)
 
                def _quiltpatchpath(self, file):
                        return os.path.join(self.dir, "patches", os.path.basename(file))
@@ -174,15 +215,15 @@ def patch_init(d):
                def __init__(self, dir, d):
                        PatchSet.__init__(self, dir, d)
                        self.initialized = False
+                       p = os.path.join(self.dir, 'patches')
+                       if not os.path.exists(p):
+                               os.makedirs(p)
 
                def Clean(self):
                        try:
                                self._runcmd(["pop", "-a", "-f"])
-                       except CmdError:
-                               pass
-                       except NotFoundError:
+                       except Exception:
                                pass
-                       # runcmd(["rm", "-rf", os.path.join(self.dir, "patches"), os.path.join(self.dir, ".pc")])
                        self.initialized = True
 
                def InitFromDir(self):
@@ -206,6 +247,7 @@ def patch_init(d):
                                try:
                                        output = runcmd(["quilt", "applied"], self.dir)
                                except CmdError:
+                                       import sys
                                        if sys.exc_value.output.strip() == "No patches applied":
                                                return
                                        else:
@@ -224,6 +266,7 @@ def patch_init(d):
                        args = ["import", "-p", patch["strippath"]]
                        if force:
                                args.append("-f")
+                               args.append("-dn")
                        args.append(patch["file"])
 
                        self._runcmd(args)
@@ -238,7 +281,7 @@ def patch_init(d):
                        self.patches.insert(self._current or 0, patch)
 
 
-               def Push(self, force = None, all = None):
+               def Push(self, force = False, all = False, run = True):
                        # quilt push [-f]
 
                        args = ["push"]
@@ -246,6 +289,8 @@ def patch_init(d):
                                args.append("-f")
                        if all:
                                args.append("-a")
+                       if not run:
+                               return self._runcmd(args, run)
 
                        self._runcmd(args)
 
@@ -306,6 +351,20 @@ def patch_init(d):
                def Finalize(self):
                        raise NotImplementedError()
 
+       class NOOPResolver(Resolver):
+               def __init__(self, patchset):
+                       self.patchset = patchset
+
+               def Resolve(self):
+                       olddir = os.path.abspath(os.curdir)
+                       os.chdir(self.patchset.dir)
+                       try:
+                               self.patchset.Push()
+                       except Exception:
+                               import sys
+                               os.chdir(olddir)
+                               raise sys.exc_value
+
        # Patch resolver which relies on the user doing all the work involved in the
        # resolution, with the exception of refreshing the remote copy of the patch
        # files (the urls).
@@ -319,16 +378,34 @@ def patch_init(d):
 
                        olddir = os.path.abspath(os.curdir)
                        os.chdir(self.patchset.dir)
-                       try:
-                               self.patchset.Push(True)
-                       except CmdError, v:
-                               # Patch application failed
-                               if sys.exc_value.output.strip() == "No patches applied":
-                                       return
-                               print(sys.exc_value)
-                               print('NOTE: dropping user into a shell, so that patch rejects can be fixed manually.')
-
-                               os.system('/bin/sh')
+                       try:
+                               self.patchset.Push(False)
+                       except CmdError, v:
+                               # Patch application failed
+                               patchcmd = self.patchset.Push(True, False, False)
+                               t = bb.data.getVar('T', d, 1)
+                               if not t:
+                                       bb.msg.fatal(bb.msg.domain.Build, "T not set")
+                               bb.mkdirhier(t)
+                               import random
+                               rcfile = "%s/bashrc.%s.%s" % (t, str(os.getpid()), random.random())
+                               f = open(rcfile, "w")
+                               f.write("echo '*** Manual patch resolution mode ***'\n")
+                               f.write("echo 'Dropping to a shell, so patch rejects can be fixed manually.'\n")
+                               f.write("echo 'Run \"quilt refresh\" when patch is corrected, press CTRL+D to exit.'\n")
+                               f.write("echo ''\n")
+                               f.write(" ".join(patchcmd) + "\n")
+                               f.write("#" + bb.data.getVar('TERMCMDRUN', d, 1))
+                               f.close()
+                               os.chmod(rcfile, 0775)
+                               os.environ['TERMWINDOWTITLE'] = "Bitbake: Please fix patch rejects manually"
+                               os.environ['TERMRCFILE'] = rcfile
+                               rc = os.system(bb.data.getVar('TERMCMDRUN', d, 1))
+                               if os.WIFEXITED(rc) and os.WEXITSTATUS(rc) != 0:
+                                       bb.msg.fatal(bb.msg.domain.Build, ("Cannot proceed with manual patch resolution - '%s' not found. " \
+                                           + "Check TERMCMDRUN variable.") % bb.data.getVar('TERMCMDRUN', d, 1))
 
                                # Construct a new PatchSet after the user's changes, compare the
                                # sets, checking patches for modifications, and doing a remote
@@ -357,29 +434,24 @@ def patch_init(d):
                                raise
                        os.chdir(olddir)
 
-               # Throw away the changes to the patches in the patchset made by resolve()
-               def Revert(self):
-                       raise NotImplementedError()
-
-               # Apply the changes to the patches in the patchset made by resolve()
-               def Finalize(self):
-                       raise NotImplementedError()
-
        g = globals()
        g["PatchSet"] = PatchSet
        g["PatchTree"] = PatchTree
        g["QuiltTree"] = QuiltTree
+       g["GitApplyTree"] = GitApplyTree
        g["Resolver"] = Resolver
        g["UserResolver"] = UserResolver
+       g["NOOPResolver"] = NOOPResolver
        g["NotFoundError"] = NotFoundError
        g["CmdError"] = CmdError
 
 addtask patch after do_unpack
 do_patch[dirs] = "${WORKDIR}"
-python patch_do_patch() {
-       import re
-       import bb.fetch
 
+PATCHDEPENDENCY = "${PATCHTOOL}-native:do_populate_staging"
+do_patch[depends] = "${PATCHDEPENDENCY}"
+
+python patch_do_patch() {
        patch_init(d)
 
        src_uri = (bb.data.getVar('SRC_URI', d, 1) or '').split()
@@ -389,11 +461,13 @@ python patch_do_patch() {
        patchsetmap = {
                "patch": PatchTree,
                "quilt": QuiltTree,
+               "git": GitApplyTree,
        }
 
        cls = patchsetmap[bb.data.getVar('PATCHTOOL', d, 1) or 'quilt']
 
        resolvermap = {
+               "noop": NOOPResolver,
                "user": UserResolver,
        }
 
@@ -436,38 +510,40 @@ python patch_do_patch() {
                else:
                        pname = os.path.basename(unpacked)
 
-               if "mindate" in parm:
-                       mindate = parm["mindate"]
-               else:
-                       mindate = 0
-
-               if "maxdate" in parm:
-                       maxdate = parm["maxdate"]
-               else:
-                       maxdate = "20711226"
-
-               pn = bb.data.getVar('PN', d, 1)
-               srcdate = bb.data.getVar('SRCDATE_%s' % pn, d, 1)
+                if "mindate" in parm or "maxdate" in parm:
+                       pn = bb.data.getVar('PN', d, 1)
+                       srcdate = bb.data.getVar('SRCDATE_%s' % pn, d, 1)
+                       if not srcdate:
+                               srcdate = bb.data.getVar('SRCDATE', d, 1)
 
-               if not srcdate:
-                       srcdate = bb.data.getVar('SRCDATE', d, 1)
+                       if srcdate == "now":
+                               srcdate = bb.data.getVar('DATE', d, 1)
 
-               if srcdate == "now":
-                       srcdate = bb.data.getVar('DATE', d, 1)
-
-               if (maxdate < srcdate) or (mindate > srcdate):
-                       if (maxdate < srcdate):
+                       if "maxdate" in parm and parm["maxdate"] < srcdate:
                                bb.note("Patch '%s' is outdated" % pname)
+                               continue
 
-                       if (mindate > srcdate):
+                       if "mindate" in parm and parm["mindate"] > srcdate:
                                bb.note("Patch '%s' is predated" % pname)
+                               continue
 
-                       continue
 
-               bb.note("Applying patch '%s'" % pname)
+               if "minrev" in parm:
+                       srcrev = bb.data.getVar('SRCREV', d, 1)
+                       if srcrev and srcrev < parm["minrev"]:
+                               bb.note("Patch '%s' applies to later revisions" % pname)
+                               continue
+
+               if "maxrev" in parm:
+                       srcrev = bb.data.getVar('SRCREV', d, 1)         
+                       if srcrev and srcrev > parm["maxrev"]:
+                               bb.note("Patch '%s' applies to earlier revisions" % pname)
+                               continue
+
+               bb.note("Applying patch '%s' (%s)" % (pname, base_path_out(unpacked, d)))
                try:
                        patchset.Import({"file":unpacked, "remote":url, "strippath": pnum}, True)
-               except NotFoundError:
+               except:
                        import sys
                        raise bb.build.FuncFailed(str(sys.exc_value))
                resolver.Resolve()