diff options
Diffstat (limited to 'meta/lib')
-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): | |||
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 | ||