diff options
Diffstat (limited to 'meta/lib/oe')
-rw-r--r-- | meta/lib/oe/patch.py | 109 |
1 files changed, 70 insertions, 39 deletions
diff --git a/meta/lib/oe/patch.py b/meta/lib/oe/patch.py index 3ded5f3601..60a0cc8291 100644 --- a/meta/lib/oe/patch.py +++ b/meta/lib/oe/patch.py | |||
@@ -294,8 +294,9 @@ class PatchTree(PatchSet): | |||
294 | self.Pop(all=True) | 294 | self.Pop(all=True) |
295 | 295 | ||
296 | class GitApplyTree(PatchTree): | 296 | class GitApplyTree(PatchTree): |
297 | patch_line_prefix = '%% original patch' | 297 | notes_ref = "refs/notes/devtool" |
298 | ignore_commit_prefix = '%% ignore' | 298 | original_patch = 'original patch' |
299 | ignore_commit = 'ignore' | ||
299 | 300 | ||
300 | def __init__(self, dir, d): | 301 | def __init__(self, dir, d): |
301 | PatchTree.__init__(self, dir, d) | 302 | PatchTree.__init__(self, dir, d) |
@@ -452,7 +453,7 @@ class GitApplyTree(PatchTree): | |||
452 | # Prepare git command | 453 | # Prepare git command |
453 | cmd = ["git"] | 454 | cmd = ["git"] |
454 | GitApplyTree.gitCommandUserOptions(cmd, commituser, commitemail) | 455 | GitApplyTree.gitCommandUserOptions(cmd, commituser, commitemail) |
455 | cmd += ["commit", "-F", tmpfile] | 456 | cmd += ["commit", "-F", tmpfile, "--no-verify"] |
456 | # git doesn't like plain email addresses as authors | 457 | # git doesn't like plain email addresses as authors |
457 | if author and '<' in author: | 458 | if author and '<' in author: |
458 | cmd.append('--author="%s"' % author) | 459 | cmd.append('--author="%s"' % author) |
@@ -461,14 +462,52 @@ class GitApplyTree(PatchTree): | |||
461 | return (tmpfile, cmd) | 462 | return (tmpfile, cmd) |
462 | 463 | ||
463 | @staticmethod | 464 | @staticmethod |
465 | def addNote(repo, ref, key, value=None): | ||
466 | note = key + (": %s" % value if value else "") | ||
467 | notes_ref = GitApplyTree.notes_ref | ||
468 | runcmd(["git", "config", "notes.rewriteMode", "ignore"], repo) | ||
469 | runcmd(["git", "config", "notes.displayRef", notes_ref, notes_ref], repo) | ||
470 | runcmd(["git", "config", "notes.rewriteRef", notes_ref, notes_ref], repo) | ||
471 | runcmd(["git", "notes", "--ref", notes_ref, "append", "-m", note, ref], repo) | ||
472 | |||
473 | @staticmethod | ||
474 | def removeNote(repo, ref, key): | ||
475 | notes = GitApplyTree.getNotes(repo, ref) | ||
476 | notes = {k: v for k, v in notes.items() if k != key and not k.startswith(key + ":")} | ||
477 | runcmd(["git", "notes", "--ref", GitApplyTree.notes_ref, "remove", "--ignore-missing", ref], repo) | ||
478 | for note, value in notes.items(): | ||
479 | GitApplyTree.addNote(repo, ref, note, value) | ||
480 | |||
481 | @staticmethod | ||
482 | def getNotes(repo, ref): | ||
483 | import re | ||
484 | |||
485 | note = None | ||
486 | try: | ||
487 | note = runcmd(["git", "notes", "--ref", GitApplyTree.notes_ref, "show", ref], repo) | ||
488 | prefix = "" | ||
489 | except CmdError: | ||
490 | note = runcmd(['git', 'show', '-s', '--format=%B', ref], repo) | ||
491 | prefix = "%% " | ||
492 | |||
493 | note_re = re.compile(r'^%s(.*?)(?::\s*(.*))?$' % prefix) | ||
494 | notes = dict() | ||
495 | for line in note.splitlines(): | ||
496 | m = note_re.match(line) | ||
497 | if m: | ||
498 | notes[m.group(1)] = m.group(2) | ||
499 | |||
500 | return notes | ||
501 | |||
502 | @staticmethod | ||
464 | def commitIgnored(subject, dir=None, files=None, d=None): | 503 | def commitIgnored(subject, dir=None, files=None, d=None): |
465 | if files: | 504 | if files: |
466 | runcmd(['git', 'add'] + files, dir) | 505 | runcmd(['git', 'add'] + files, dir) |
467 | message = "%s\n\n%s" % (subject, GitApplyTree.ignore_commit_prefix) | ||
468 | cmd = ["git"] | 506 | cmd = ["git"] |
469 | GitApplyTree.gitCommandUserOptions(cmd, d=d) | 507 | GitApplyTree.gitCommandUserOptions(cmd, d=d) |
470 | cmd += ["commit", "-m", message, "--no-verify"] | 508 | cmd += ["commit", "-m", subject, "--no-verify"] |
471 | runcmd(cmd, dir) | 509 | runcmd(cmd, dir) |
510 | GitApplyTree.addNote(dir, "HEAD", GitApplyTree.ignore_commit) | ||
472 | 511 | ||
473 | @staticmethod | 512 | @staticmethod |
474 | def extractPatches(tree, startcommits, outdir, paths=None): | 513 | def extractPatches(tree, startcommits, outdir, paths=None): |
@@ -484,18 +523,20 @@ class GitApplyTree(PatchTree): | |||
484 | out = runcmd(["sh", "-c", " ".join(shellcmd)], os.path.join(tree, name)) | 523 | out = runcmd(["sh", "-c", " ".join(shellcmd)], os.path.join(tree, name)) |
485 | if out: | 524 | if out: |
486 | for srcfile in out.split(): | 525 | for srcfile in out.split(): |
487 | outfile = os.path.basename(srcfile) | 526 | # This loop, which is used to remove any line that |
527 | # starts with "%% original patch", is kept for backwards | ||
528 | # compatibility. If/when that compatibility is dropped, | ||
529 | # it can be replaced with code to just read the first | ||
530 | # line of the patch file to get the SHA-1, and the code | ||
531 | # below that writes the modified patch file can be | ||
532 | # replaced with a simple file move. | ||
488 | for encoding in ['utf-8', 'latin-1']: | 533 | for encoding in ['utf-8', 'latin-1']: |
489 | patchlines = [] | 534 | patchlines = [] |
490 | try: | 535 | try: |
491 | with open(srcfile, 'r', encoding=encoding, newline='') as f: | 536 | with open(srcfile, 'r', encoding=encoding, newline='') as f: |
492 | for line in f: | 537 | for line in f: |
493 | if line.startswith(GitApplyTree.patch_line_prefix): | 538 | if line.startswith("%% " + GitApplyTree.original_patch): |
494 | outfile = line.split()[-1].strip() | ||
495 | continue | 539 | continue |
496 | if line.startswith(GitApplyTree.ignore_commit_prefix): | ||
497 | outfile = None | ||
498 | break | ||
499 | patchlines.append(line) | 540 | patchlines.append(line) |
500 | except UnicodeDecodeError: | 541 | except UnicodeDecodeError: |
501 | continue | 542 | continue |
@@ -503,11 +544,16 @@ class GitApplyTree(PatchTree): | |||
503 | else: | 544 | else: |
504 | raise PatchError('Unable to find a character encoding to decode %s' % srcfile) | 545 | raise PatchError('Unable to find a character encoding to decode %s' % srcfile) |
505 | 546 | ||
506 | if outfile: | 547 | sha1 = patchlines[0].split()[1] |
507 | bb.utils.mkdirhier(os.path.join(outdir, name)) | 548 | notes = GitApplyTree.getNotes(os.path.join(tree, name), sha1) |
508 | with open(os.path.join(outdir, name, outfile), 'w') as of: | 549 | if GitApplyTree.ignore_commit in notes: |
509 | for line in patchlines: | 550 | continue |
510 | of.write(line) | 551 | outfile = notes.get(GitApplyTree.original_patch, os.path.basename(srcfile)) |
552 | |||
553 | bb.utils.mkdirhier(os.path.join(outdir, name)) | ||
554 | with open(os.path.join(outdir, name, outfile), 'w') as of: | ||
555 | for line in patchlines: | ||
556 | of.write(line) | ||
511 | finally: | 557 | finally: |
512 | shutil.rmtree(tempdir) | 558 | shutil.rmtree(tempdir) |
513 | 559 | ||
@@ -555,28 +601,11 @@ class GitApplyTree(PatchTree): | |||
555 | 601 | ||
556 | return runcmd(["sh", "-c", " ".join(shellcmd)], self.dir) | 602 | return runcmd(["sh", "-c", " ".join(shellcmd)], self.dir) |
557 | 603 | ||
558 | # Add hooks which add a pointer to the original patch file name in the commit message | ||
559 | reporoot = (runcmd("git rev-parse --show-toplevel".split(), self.dir) or '').strip() | 604 | reporoot = (runcmd("git rev-parse --show-toplevel".split(), self.dir) or '').strip() |
560 | if not reporoot: | 605 | if not reporoot: |
561 | raise Exception("Cannot get repository root for directory %s" % self.dir) | 606 | raise Exception("Cannot get repository root for directory %s" % self.dir) |
562 | gitdir = (runcmd("git rev-parse --absolute-git-dir".split(), self.dir) or '').strip() | 607 | |
563 | if not gitdir: | 608 | patch_applied = True |
564 | raise Exception("Cannot get gitdir for directory %s" % self.dir) | ||
565 | hooks_dir = os.path.join(gitdir, 'hooks') | ||
566 | hooks_dir_backup = hooks_dir + '.devtool-orig' | ||
567 | if os.path.lexists(hooks_dir_backup): | ||
568 | raise Exception("Git hooks backup directory already exists: %s" % hooks_dir_backup) | ||
569 | if os.path.lexists(hooks_dir): | ||
570 | shutil.move(hooks_dir, hooks_dir_backup) | ||
571 | os.mkdir(hooks_dir) | ||
572 | commithook = os.path.join(hooks_dir, 'commit-msg') | ||
573 | applyhook = os.path.join(hooks_dir, 'applypatch-msg') | ||
574 | with open(commithook, 'w') as f: | ||
575 | # NOTE: the formatting here is significant; if you change it you'll also need to | ||
576 | # change other places which read it back | ||
577 | f.write('echo "\n%s: $PATCHFILE" >> $1' % GitApplyTree.patch_line_prefix) | ||
578 | os.chmod(commithook, 0o755) | ||
579 | shutil.copy2(commithook, applyhook) | ||
580 | try: | 609 | try: |
581 | patchfilevar = 'PATCHFILE="%s"' % os.path.basename(patch['file']) | 610 | patchfilevar = 'PATCHFILE="%s"' % os.path.basename(patch['file']) |
582 | if self._need_dirty_check(): | 611 | if self._need_dirty_check(): |
@@ -587,7 +616,7 @@ class GitApplyTree(PatchTree): | |||
587 | pass | 616 | pass |
588 | else: | 617 | else: |
589 | if output: | 618 | if output: |
590 | # The tree is dirty, not need to try to apply patches with git anymore | 619 | # The tree is dirty, no need to try to apply patches with git anymore |
591 | # since they fail, fallback directly to patch | 620 | # since they fail, fallback directly to patch |
592 | output = PatchTree._applypatch(self, patch, force, reverse, run) | 621 | output = PatchTree._applypatch(self, patch, force, reverse, run) |
593 | output += self._commitpatch(patch, patchfilevar) | 622 | output += self._commitpatch(patch, patchfilevar) |
@@ -620,10 +649,12 @@ class GitApplyTree(PatchTree): | |||
620 | output = PatchTree._applypatch(self, patch, force, reverse, run) | 649 | output = PatchTree._applypatch(self, patch, force, reverse, run) |
621 | output += self._commitpatch(patch, patchfilevar) | 650 | output += self._commitpatch(patch, patchfilevar) |
622 | return output | 651 | return output |
652 | except: | ||
653 | patch_applied = False | ||
654 | raise | ||
623 | finally: | 655 | finally: |
624 | shutil.rmtree(hooks_dir) | 656 | if patch_applied: |
625 | if os.path.lexists(hooks_dir_backup): | 657 | GitApplyTree.addNote(self.dir, "HEAD", GitApplyTree.original_patch, os.path.basename(patch['file'])) |
626 | shutil.move(hooks_dir_backup, hooks_dir) | ||
627 | 658 | ||
628 | 659 | ||
629 | class QuiltTree(PatchSet): | 660 | class QuiltTree(PatchSet): |