diff options
author | Paul Eggleton <paul.eggleton@linux.intel.com> | 2015-10-11 15:41:20 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-12-01 21:32:03 +0000 |
commit | a360fa7d519320faf53065ba9584a426fd275c1a (patch) | |
tree | b0c2809259ff8b05d220ed8ea3d6dfad760bf64f | |
parent | f79cc4d9c37cc8b08b51491f335119b8caf84671 (diff) | |
download | poky-a360fa7d519320faf53065ba9584a426fd275c1a.tar.gz |
lib/oe/patch: improve extraction of patch header
For patches that we have to extract the header information by hand (i.e.
will not apply with "git am"), make the following improvements:
* If we can't extract author/date/subject, then try to do so from the
commit that added the patch in git (assuming the metadata is tracked
by git)
* Take only first Signed-off-by line instead of last
* Accept any case for "Signed-off-by" in case author has typed it by
hand
* Improve conditional - we can skip the other cases if one matches
Implements [YOCTO #7624].
(From OE-Core rev: 13ec296b5c35aefa2c44f64f8bd1ef54c4a0a731)
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | meta/lib/oe/patch.py | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/meta/lib/oe/patch.py b/meta/lib/oe/patch.py index 2bf501e9e6..2255ce437b 100644 --- a/meta/lib/oe/patch.py +++ b/meta/lib/oe/patch.py | |||
@@ -282,33 +282,32 @@ class GitApplyTree(PatchTree): | |||
282 | return lines | 282 | return lines |
283 | 283 | ||
284 | @staticmethod | 284 | @staticmethod |
285 | def prepareCommit(patchfile): | 285 | def decodeAuthor(line): |
286 | """ | 286 | from email.header import decode_header |
287 | Prepare a git commit command line based on the header from a patch file | 287 | authorval = line.split(':', 1)[1].strip().replace('"', '') |
288 | (typically this is useful for patches that cannot be applied with "git am" due to formatting) | 288 | return decode_header(authorval)[0][0] |
289 | """ | 289 | |
290 | import tempfile | 290 | @staticmethod |
291 | def interpretPatchHeader(headerlines): | ||
291 | import re | 292 | import re |
292 | author_re = re.compile('[\S ]+ <\S+@\S+\.\S+>') | 293 | author_re = re.compile('[\S ]+ <\S+@\S+\.\S+>') |
293 | # Process patch header and extract useful information | ||
294 | lines = GitApplyTree.extractPatchHeader(patchfile) | ||
295 | outlines = [] | 294 | outlines = [] |
296 | author = None | 295 | author = None |
297 | date = None | 296 | date = None |
298 | for line in lines: | 297 | subject = None |
298 | for line in headerlines: | ||
299 | if line.startswith('Subject: '): | 299 | if line.startswith('Subject: '): |
300 | subject = line.split(':', 1)[1] | 300 | subject = line.split(':', 1)[1] |
301 | # Remove any [PATCH][oe-core] etc. | 301 | # Remove any [PATCH][oe-core] etc. |
302 | subject = re.sub(r'\[.+?\]\s*', '', subject) | 302 | subject = re.sub(r'\[.+?\]\s*', '', subject) |
303 | outlines.insert(0, '%s\n\n' % subject.strip()) | ||
304 | continue | 303 | continue |
305 | if line.startswith('From: ') or line.startswith('Author: '): | 304 | elif line.startswith('From: ') or line.startswith('Author: '): |
306 | authorval = line.split(':', 1)[1].strip().replace('"', '') | 305 | authorval = GitApplyTree.decodeAuthor(line) |
307 | # git is fussy about author formatting i.e. it must be Name <email@domain> | 306 | # git is fussy about author formatting i.e. it must be Name <email@domain> |
308 | if author_re.match(authorval): | 307 | if author_re.match(authorval): |
309 | author = authorval | 308 | author = authorval |
310 | continue | 309 | continue |
311 | if line.startswith('Date: '): | 310 | elif line.startswith('Date: '): |
312 | if date is None: | 311 | if date is None: |
313 | dateval = line.split(':', 1)[1].strip() | 312 | dateval = line.split(':', 1)[1].strip() |
314 | # Very crude check for date format, since git will blow up if it's not in the right | 313 | # Very crude check for date format, since git will blow up if it's not in the right |
@@ -316,12 +315,41 @@ class GitApplyTree(PatchTree): | |||
316 | if len(dateval) > 12: | 315 | if len(dateval) > 12: |
317 | date = dateval | 316 | date = dateval |
318 | continue | 317 | continue |
319 | if line.startswith('Signed-off-by: '): | 318 | elif not author and line.lower().startswith('signed-off-by: '): |
320 | authorval = line.split(':', 1)[1].strip().replace('"', '') | 319 | authorval = GitApplyTree.decodeAuthor(line) |
321 | # git is fussy about author formatting i.e. it must be Name <email@domain> | 320 | # git is fussy about author formatting i.e. it must be Name <email@domain> |
322 | if author_re.match(authorval): | 321 | if author_re.match(authorval): |
323 | author = authorval | 322 | author = authorval |
324 | outlines.append(line) | 323 | outlines.append(line) |
324 | return outlines, author, date, subject | ||
325 | |||
326 | @staticmethod | ||
327 | def prepareCommit(patchfile): | ||
328 | """ | ||
329 | Prepare a git commit command line based on the header from a patch file | ||
330 | (typically this is useful for patches that cannot be applied with "git am" due to formatting) | ||
331 | """ | ||
332 | import tempfile | ||
333 | # Process patch header and extract useful information | ||
334 | lines = GitApplyTree.extractPatchHeader(patchfile) | ||
335 | outlines, author, date, subject = GitApplyTree.interpretPatchHeader(lines) | ||
336 | if not author or not subject: | ||
337 | try: | ||
338 | shellcmd = ["git", "log", "--format=email", "--diff-filter=A", "--", patchfile] | ||
339 | out = runcmd(["sh", "-c", " ".join(shellcmd)], os.path.dirname(patchfile)) | ||
340 | except CmdError: | ||
341 | out = None | ||
342 | if out: | ||
343 | _, newauthor, newdate, newsubject = GitApplyTree.interpretPatchHeader(out.splitlines()) | ||
344 | if not author or not date: | ||
345 | # These really need to go together | ||
346 | author = newauthor | ||
347 | date = newdate | ||
348 | if not subject: | ||
349 | subject = newsubject | ||
350 | if subject: | ||
351 | outlines.insert(0, '%s\n\n' % subject.strip()) | ||
352 | |||
325 | # Write out commit message to a file | 353 | # Write out commit message to a file |
326 | with tempfile.NamedTemporaryFile('w', delete=False) as tf: | 354 | with tempfile.NamedTemporaryFile('w', delete=False) as tf: |
327 | tmpfile = tf.name | 355 | tmpfile = tf.name |