summaryrefslogtreecommitdiffstats
path: root/meta/lib/oe/patch.py
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oe/patch.py')
-rw-r--r--meta/lib/oe/patch.py86
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):
202 def __init__(self, dir, d): 202 def __init__(self, dir, d):
203 PatchTree.__init__(self, dir, d) 203 PatchTree.__init__(self, dir, d)
204 204
205 @staticmethod
206 def extractPatchHeader(patchfile):
207 """
208 Extract just the header lines from the top of a patch file
209 """
210 lines = []
211 with open(patchfile, 'r') as f:
212 for line in f.readlines():
213 if line.startswith('Index: ') or line.startswith('diff -') or line.startswith('---'):
214 break
215 lines.append(line)
216 return lines
217
218 @staticmethod
219 def prepareCommit(patchfile):
220 """
221 Prepare a git commit command line based on the header from a patch file
222 (typically this is useful for patches that cannot be applied with "git am" due to formatting)
223 """
224 import tempfile
225 import re
226 author_re = re.compile('[\S ]+ <\S+@\S+\.\S+>')
227 # Process patch header and extract useful information
228 lines = GitApplyTree.extractPatchHeader(patchfile)
229 outlines = []
230 author = None
231 date = None
232 for line in lines:
233 if line.startswith('Subject: '):
234 subject = line.split(':', 1)[1]
235 # Remove any [PATCH][oe-core] etc.
236 subject = re.sub(r'\[.+?\]\s*', '', subject)
237 outlines.insert(0, '%s\n\n' % subject.strip())
238 continue
239 if line.startswith('From: ') or line.startswith('Author: '):
240 authorval = line.split(':', 1)[1].strip().replace('"', '')
241 # git is fussy about author formatting i.e. it must be Name <email@domain>
242 if author_re.match(authorval):
243 author = authorval
244 continue
245 if line.startswith('Date: '):
246 if date is None:
247 dateval = line.split(':', 1)[1].strip()
248 # Very crude check for date format, since git will blow up if it's not in the right
249 # format. Without e.g. a python-dateutils dependency we can't do a whole lot more
250 if len(dateval) > 12:
251 date = dateval
252 continue
253 if line.startswith('Signed-off-by: '):
254 authorval = line.split(':', 1)[1].strip().replace('"', '')
255 # git is fussy about author formatting i.e. it must be Name <email@domain>
256 if author_re.match(authorval):
257 author = authorval
258 outlines.append(line)
259 # Add a pointer to the original patch file name
260 if outlines and outlines[-1].strip():
261 outlines.append('\n')
262 outlines.append('(from original patch: %s)\n' % os.path.basename(patchfile))
263 # Write out commit message to a file
264 with tempfile.NamedTemporaryFile('w', delete=False) as tf:
265 tmpfile = tf.name
266 for line in outlines:
267 tf.write(line)
268 # Prepare git command
269 cmd = ["git", "commit", "-F", tmpfile]
270 # git doesn't like plain email addresses as authors
271 if author and '<' in author:
272 cmd.append('--author="%s"' % author)
273 if date:
274 cmd.append('--date="%s"' % date)
275 return (tmpfile, cmd)
276
205 def _applypatch(self, patch, force = False, reverse = False, run = True): 277 def _applypatch(self, patch, force = False, reverse = False, run = True):
206 def _applypatchhelper(shellcmd, patch, force = False, reverse = False, run = True): 278 def _applypatchhelper(shellcmd, patch, force = False, reverse = False, run = True):
207 if reverse: 279 if reverse:
@@ -218,11 +290,25 @@ class GitApplyTree(PatchTree):
218 shellcmd = ["git", "--work-tree=.", "am", "-3", "-p%s" % patch['strippath']] 290 shellcmd = ["git", "--work-tree=.", "am", "-3", "-p%s" % patch['strippath']]
219 return _applypatchhelper(shellcmd, patch, force, reverse, run) 291 return _applypatchhelper(shellcmd, patch, force, reverse, run)
220 except CmdError: 292 except CmdError:
293 # Fall back to git apply
221 shellcmd = ["git", "--git-dir=.", "apply", "-p%s" % patch['strippath']] 294 shellcmd = ["git", "--git-dir=.", "apply", "-p%s" % patch['strippath']]
222 try: 295 try:
223 output = _applypatchhelper(shellcmd, patch, force, reverse, run) 296 output = _applypatchhelper(shellcmd, patch, force, reverse, run)
224 except CmdError: 297 except CmdError:
298 # Fall back to patch
225 output = PatchTree._applypatch(self, patch, force, reverse, run) 299 output = PatchTree._applypatch(self, patch, force, reverse, run)
300 # Add all files
301 shellcmd = ["git", "add", "-f", "."]
302 output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
303 # Exclude the patches directory
304 shellcmd = ["git", "reset", "HEAD", self.patchdir]
305 output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
306 # Commit the result
307 (tmpfile, shellcmd) = self.prepareCommit(patch['file'])
308 try:
309 output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
310 finally:
311 os.remove(tmpfile)
226 return output 312 return output
227 313
228 314