patch.bbclass 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. # Copyright (C) 2006 OpenedHand LTD
  2. # Point to an empty file so any user's custom settings don't break things
  3. QUILTRCFILE ?= "${STAGING_ETCDIR_NATIVE}/quiltrc"
  4. PATCHDEPENDENCY = "${PATCHTOOL}-native:do_populate_sysroot"
  5. # There is a bug in patch 2.7.3 and earlier where index lines
  6. # in patches can change file modes when they shouldn't:
  7. # http://git.savannah.gnu.org/cgit/patch.git/patch/?id=82b800c9552a088a241457948219d25ce0a407a4
  8. # This leaks into debug sources in particular. Add the dependency
  9. # to target recipes to avoid this problem until we can rely on 2.7.4 or later.
  10. PATCHDEPENDENCY_append_class-target = " patch-replacement-native:do_populate_sysroot"
  11. PATCH_GIT_USER_NAME ?= "OpenEmbedded"
  12. PATCH_GIT_USER_EMAIL ?= "oe.patch@oe"
  13. inherit terminal
  14. python () {
  15. if d.getVar('PATCHTOOL') == 'git' and d.getVar('PATCH_COMMIT_FUNCTIONS') == '1':
  16. extratasks = bb.build.tasksbetween('do_unpack', 'do_patch', d)
  17. try:
  18. extratasks.remove('do_unpack')
  19. except ValueError:
  20. # For some recipes do_unpack doesn't exist, ignore it
  21. pass
  22. d.appendVarFlag('do_patch', 'prefuncs', ' patch_task_patch_prefunc')
  23. for task in extratasks:
  24. d.appendVarFlag(task, 'postfuncs', ' patch_task_postfunc')
  25. }
  26. python patch_task_patch_prefunc() {
  27. # Prefunc for do_patch
  28. srcsubdir = d.getVar('S')
  29. workdir = os.path.abspath(d.getVar('WORKDIR'))
  30. testsrcdir = os.path.abspath(srcsubdir)
  31. if (testsrcdir + os.sep).startswith(workdir + os.sep):
  32. # Double-check that either workdir or S or some directory in-between is a git repository
  33. found = False
  34. while testsrcdir != workdir:
  35. if os.path.exists(os.path.join(testsrcdir, '.git')):
  36. found = True
  37. break
  38. if testsrcdir == workdir:
  39. break
  40. testsrcdir = os.path.dirname(testsrcdir)
  41. if not found:
  42. bb.fatal('PATCHTOOL = "git" set for source tree that is not a git repository. Refusing to continue as that may result in commits being made in your metadata repository.')
  43. patchdir = os.path.join(srcsubdir, 'patches')
  44. if os.path.exists(patchdir):
  45. if os.listdir(patchdir):
  46. d.setVar('PATCH_HAS_PATCHES_DIR', '1')
  47. else:
  48. os.rmdir(patchdir)
  49. }
  50. python patch_task_postfunc() {
  51. # Prefunc for task functions between do_unpack and do_patch
  52. import oe.patch
  53. import shutil
  54. func = d.getVar('BB_RUNTASK')
  55. srcsubdir = d.getVar('S')
  56. if os.path.exists(srcsubdir):
  57. if func == 'do_patch':
  58. haspatches = (d.getVar('PATCH_HAS_PATCHES_DIR') == '1')
  59. patchdir = os.path.join(srcsubdir, 'patches')
  60. if os.path.exists(patchdir):
  61. shutil.rmtree(patchdir)
  62. if haspatches:
  63. stdout, _ = bb.process.run('git status --porcelain patches', cwd=srcsubdir)
  64. if stdout:
  65. bb.process.run('git checkout patches', cwd=srcsubdir)
  66. stdout, _ = bb.process.run('git status --porcelain .', cwd=srcsubdir)
  67. if stdout:
  68. useroptions = []
  69. oe.patch.GitApplyTree.gitCommandUserOptions(useroptions, d=d)
  70. bb.process.run('git add .; git %s commit -a -m "Committing changes from %s\n\n%s"' % (' '.join(useroptions), func, oe.patch.GitApplyTree.ignore_commit_prefix + ' - from %s' % func), cwd=srcsubdir)
  71. }
  72. def src_patches(d, all=False, expand=True):
  73. import oe.patch
  74. return oe.patch.src_patches(d, all, expand)
  75. def should_apply(parm, d):
  76. """Determine if we should apply the given patch"""
  77. import oe.patch
  78. return oe.patch.should_apply(parm, d)
  79. should_apply[vardepsexclude] = "DATE SRCDATE"
  80. python patch_do_patch() {
  81. import oe.patch
  82. patchsetmap = {
  83. "patch": oe.patch.PatchTree,
  84. "quilt": oe.patch.QuiltTree,
  85. "git": oe.patch.GitApplyTree,
  86. }
  87. cls = patchsetmap[d.getVar('PATCHTOOL') or 'quilt']
  88. resolvermap = {
  89. "noop": oe.patch.NOOPResolver,
  90. "user": oe.patch.UserResolver,
  91. }
  92. rcls = resolvermap[d.getVar('PATCHRESOLVE') or 'user']
  93. classes = {}
  94. s = d.getVar('S')
  95. os.putenv('PATH', d.getVar('PATH'))
  96. # We must use one TMPDIR per process so that the "patch" processes
  97. # don't generate the same temp file name.
  98. import tempfile
  99. process_tmpdir = tempfile.mkdtemp()
  100. os.environ['TMPDIR'] = process_tmpdir
  101. for patch in src_patches(d):
  102. _, _, local, _, _, parm = bb.fetch.decodeurl(patch)
  103. if "patchdir" in parm:
  104. patchdir = parm["patchdir"]
  105. if not os.path.isabs(patchdir):
  106. patchdir = os.path.join(s, patchdir)
  107. else:
  108. patchdir = s
  109. if not patchdir in classes:
  110. patchset = cls(patchdir, d)
  111. resolver = rcls(patchset, oe_terminal)
  112. classes[patchdir] = (patchset, resolver)
  113. patchset.Clean()
  114. else:
  115. patchset, resolver = classes[patchdir]
  116. bb.note("Applying patch '%s' (%s)" % (parm['patchname'], oe.path.format_display(local, d)))
  117. try:
  118. patchset.Import({"file":local, "strippath": parm['striplevel']}, True)
  119. except Exception as exc:
  120. bb.utils.remove(process_tmpdir, True)
  121. bb.fatal(str(exc))
  122. try:
  123. resolver.Resolve()
  124. except bb.BBHandledException as e:
  125. bb.utils.remove(process_tmpdir, True)
  126. bb.fatal(str(e))
  127. bb.utils.remove(process_tmpdir, True)
  128. del os.environ['TMPDIR']
  129. }
  130. patch_do_patch[vardepsexclude] = "PATCHRESOLVE"
  131. addtask patch after do_unpack
  132. do_patch[umask] = "022"
  133. do_patch[dirs] = "${WORKDIR}"
  134. do_patch[depends] = "${PATCHDEPENDENCY}"
  135. EXPORT_FUNCTIONS do_patch