lib/oe/patch: add support for extracting patches from git tree

When patches from a recipe have been written out to a git tree, we also
want to be able to do the reverse so we can update the patches next to
the recipe. This is implemented by adding a comment to each commit
message (using git hooks) which we can extract later on.

(From OE-Core rev: 765b7bad50eae5b79d13a3f4988dc440c3d9787f)

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Paul Eggleton
2014-12-19 11:41:49 +00:00
committed by Richard Purdie
parent 50e771d114
commit 12bb32e766

View File

@@ -199,6 +199,8 @@ class PatchTree(PatchSet):
self.Pop(all=True)
class GitApplyTree(PatchTree):
patch_line_prefix = '%% original patch'
def __init__(self, dir, d):
PatchTree.__init__(self, dir, d)
@@ -256,10 +258,6 @@ class GitApplyTree(PatchTree):
if author_re.match(authorval):
author = authorval
outlines.append(line)
# Add a pointer to the original patch file name
if outlines and outlines[-1].strip():
outlines.append('\n')
outlines.append('(from original patch: %s)\n' % os.path.basename(patchfile))
# Write out commit message to a file
with tempfile.NamedTemporaryFile('w', delete=False) as tf:
tmpfile = tf.name
@@ -274,7 +272,35 @@ class GitApplyTree(PatchTree):
cmd.append('--date="%s"' % date)
return (tmpfile, cmd)
@staticmethod
def extractPatches(tree, startcommit, outdir):
import tempfile
import shutil
tempdir = tempfile.mkdtemp(prefix='oepatch')
try:
shellcmd = ["git", "format-patch", startcommit, "-o", tempdir]
out = runcmd(["sh", "-c", " ".join(shellcmd)], tree)
if out:
for srcfile in out.split():
patchlines = []
outfile = None
with open(srcfile, 'r') as f:
for line in f:
if line.startswith(GitApplyTree.patch_line_prefix):
outfile = line.split()[-1].strip()
continue
patchlines.append(line)
if not outfile:
outfile = os.path.basename(srcfile)
with open(os.path.join(outdir, outfile), 'w') as of:
for line in patchlines:
of.write(line)
finally:
shutil.rmtree(tempdir)
def _applypatch(self, patch, force = False, reverse = False, run = True):
import shutil
def _applypatchhelper(shellcmd, patch, force = False, reverse = False, run = True):
if reverse:
shellcmd.append('-R')
@@ -286,36 +312,62 @@ class GitApplyTree(PatchTree):
return runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
# Add hooks which add a pointer to the original patch file name in the commit message
commithook = os.path.join(self.dir, '.git', 'hooks', 'commit-msg')
commithook_backup = commithook + '.devtool-orig'
applyhook = os.path.join(self.dir, '.git', 'hooks', 'applypatch-msg')
applyhook_backup = applyhook + '.devtool-orig'
if os.path.exists(commithook):
shutil.move(commithook, commithook_backup)
if os.path.exists(applyhook):
shutil.move(applyhook, applyhook_backup)
with open(commithook, 'w') as f:
# NOTE: the formatting here is significant; if you change it you'll also need to
# change other places which read it back
f.write('echo >> $1\n')
f.write('echo "%s: $PATCHFILE" >> $1\n' % GitApplyTree.patch_line_prefix)
os.chmod(commithook, 0755)
shutil.copy2(commithook, applyhook)
try:
shellcmd = ["git", "--work-tree=.", "am", "-3", "--keep-cr", "-p%s" % patch['strippath']]
return _applypatchhelper(shellcmd, patch, force, reverse, run)
except CmdError:
# Need to abort the git am, or we'll still be within it at the end
patchfilevar = 'PATCHFILE="%s"' % os.path.basename(patch['file'])
try:
shellcmd = ["git", "--work-tree=.", "am", "--abort"]
runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
shellcmd = [patchfilevar, "git", "--work-tree=.", "am", "-3", "--keep-cr", "-p%s" % patch['strippath']]
return _applypatchhelper(shellcmd, patch, force, reverse, run)
except CmdError:
pass
# Fall back to git apply
shellcmd = ["git", "--git-dir=.", "apply", "-p%s" % patch['strippath']]
try:
output = _applypatchhelper(shellcmd, patch, force, reverse, run)
except CmdError:
# Fall back to patch
output = PatchTree._applypatch(self, patch, force, reverse, run)
# Add all files
shellcmd = ["git", "add", "-f", "."]
output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
# Exclude the patches directory
shellcmd = ["git", "reset", "HEAD", self.patchdir]
output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
# Commit the result
(tmpfile, shellcmd) = self.prepareCommit(patch['file'])
try:
# Need to abort the git am, or we'll still be within it at the end
try:
shellcmd = ["git", "--work-tree=.", "am", "--abort"]
runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
except CmdError:
pass
# Fall back to git apply
shellcmd = ["git", "--git-dir=.", "apply", "-p%s" % patch['strippath']]
try:
output = _applypatchhelper(shellcmd, patch, force, reverse, run)
except CmdError:
# Fall back to patch
output = PatchTree._applypatch(self, patch, force, reverse, run)
# Add all files
shellcmd = ["git", "add", "-f", "."]
output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
finally:
os.remove(tmpfile)
return output
# Exclude the patches directory
shellcmd = ["git", "reset", "HEAD", self.patchdir]
output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
# Commit the result
(tmpfile, shellcmd) = self.prepareCommit(patch['file'])
try:
shellcmd.insert(0, patchfilevar)
output += runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
finally:
os.remove(tmpfile)
return output
finally:
os.remove(commithook)
os.remove(applyhook)
if os.path.exists(commithook_backup):
shutil.move(commithook_backup, commithook)
if os.path.exists(applyhook_backup):
shutil.move(applyhook_backup, applyhook)
class QuiltTree(PatchSet):