summaryrefslogtreecommitdiff
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.py161
1 files changed, 147 insertions, 14 deletions
diff --git a/meta/lib/oe/patch.py b/meta/lib/oe/patch.py
index 05e0faa5b7..f1ab3dd809 100644
--- a/meta/lib/oe/patch.py
+++ b/meta/lib/oe/patch.py
@@ -81,7 +81,7 @@ class PatchSet(object):
patch[param] = PatchSet.defaults[param]
if patch.get("remote"):
- patch["file"] = bb.data.expand(bb.fetch2.localpath(patch["remote"], self.d), self.d)
+ patch["file"] = self.d.expand(bb.fetch2.localpath(patch["remote"], self.d))
patch["filemd5"] = bb.utils.md5_file(patch["file"])
@@ -281,8 +281,8 @@ class GitApplyTree(PatchTree):
def __init__(self, dir, d):
PatchTree.__init__(self, dir, d)
- self.commituser = d.getVar('PATCH_GIT_USER_NAME', True)
- self.commitemail = d.getVar('PATCH_GIT_USER_EMAIL', True)
+ self.commituser = d.getVar('PATCH_GIT_USER_NAME')
+ self.commitemail = d.getVar('PATCH_GIT_USER_EMAIL')
@staticmethod
def extractPatchHeader(patchfile):
@@ -317,6 +317,7 @@ class GitApplyTree(PatchTree):
def interpretPatchHeader(headerlines):
import re
author_re = re.compile('[\S ]+ <\S+@\S+\.\S+>')
+ from_commit_re = re.compile('^From [a-z0-9]{40} .*')
outlines = []
author = None
date = None
@@ -346,14 +347,32 @@ class GitApplyTree(PatchTree):
# git is fussy about author formatting i.e. it must be Name <email@domain>
if author_re.match(authorval):
author = authorval
+ elif from_commit_re.match(line):
+ # We don't want the From <commit> line - if it's present it will break rebasing
+ continue
outlines.append(line)
+
+ if not subject:
+ firstline = None
+ for line in headerlines:
+ line = line.strip()
+ if firstline:
+ if line:
+ # Second line is not blank, the first line probably isn't usable
+ firstline = None
+ break
+ elif line:
+ firstline = line
+ if firstline and not firstline.startswith(('#', 'Index:', 'Upstream-Status:')) and len(firstline) < 100:
+ subject = firstline
+
return outlines, author, date, subject
@staticmethod
def gitCommandUserOptions(cmd, commituser=None, commitemail=None, d=None):
if d:
- commituser = d.getVar('PATCH_GIT_USER_NAME', True)
- commitemail = d.getVar('PATCH_GIT_USER_EMAIL', True)
+ commituser = d.getVar('PATCH_GIT_USER_NAME')
+ commitemail = d.getVar('PATCH_GIT_USER_EMAIL')
if commituser:
cmd += ['-c', 'user.name="%s"' % commituser]
if commitemail:
@@ -369,21 +388,24 @@ class GitApplyTree(PatchTree):
# Process patch header and extract useful information
lines = GitApplyTree.extractPatchHeader(patchfile)
outlines, author, date, subject = GitApplyTree.interpretPatchHeader(lines)
- if not author or not subject:
+ if not author or not subject or not date:
try:
- shellcmd = ["git", "log", "--format=email", "--diff-filter=A", "--", patchfile]
+ shellcmd = ["git", "log", "--format=email", "--follow", "--diff-filter=A", "--", patchfile]
out = runcmd(["sh", "-c", " ".join(shellcmd)], os.path.dirname(patchfile))
except CmdError:
out = None
if out:
_, newauthor, newdate, newsubject = GitApplyTree.interpretPatchHeader(out.splitlines())
- if not author or not date:
- # These really need to go together
+ if not author:
+ # If we're setting the author then the date should be set as well
author = newauthor
date = newdate
+ elif not date:
+ # If we don't do this we'll get the current date, at least this will be closer
+ date = newdate
if not subject:
subject = newsubject
- if subject:
+ if subject and outlines and not outlines[0].strip() == subject:
outlines.insert(0, '%s\n\n' % subject.strip())
# Write out commit message to a file
@@ -406,6 +428,7 @@ class GitApplyTree(PatchTree):
def extractPatches(tree, startcommit, outdir, paths=None):
import tempfile
import shutil
+ import re
tempdir = tempfile.mkdtemp(prefix='oepatch')
try:
shellcmd = ["git", "format-patch", startcommit, "-o", tempdir]
@@ -421,10 +444,13 @@ class GitApplyTree(PatchTree):
try:
with open(srcfile, 'r', encoding=encoding) as f:
for line in f:
- if line.startswith(GitApplyTree.patch_line_prefix):
+ checkline = line
+ if checkline.startswith('Subject: '):
+ checkline = re.sub(r'\[.+?\]\s*', '', checkline[9:])
+ if checkline.startswith(GitApplyTree.patch_line_prefix):
outfile = line.split()[-1].strip()
continue
- if line.startswith(GitApplyTree.ignore_commit_prefix):
+ if checkline.startswith(GitApplyTree.ignore_commit_prefix):
continue
patchlines.append(line)
except UnicodeDecodeError:
@@ -525,7 +551,7 @@ class GitApplyTree(PatchTree):
class QuiltTree(PatchSet):
def _runcmd(self, args, run = True):
- quiltrc = self.d.getVar('QUILTRCFILE', True)
+ quiltrc = self.d.getVar('QUILTRCFILE')
if not run:
return ["quilt"] + ["--quiltrc"] + [quiltrc] + args
runcmd(["quilt"] + ["--quiltrc"] + [quiltrc] + args, self.dir)
@@ -701,7 +727,7 @@ class UserResolver(Resolver):
# Patch application failed
patchcmd = self.patchset.Push(True, False, False)
- t = self.patchset.d.getVar('T', True)
+ t = self.patchset.d.getVar('T')
if not t:
bb.msg.fatal("Build", "T not set")
bb.utils.mkdirhier(t)
@@ -743,3 +769,110 @@ class UserResolver(Resolver):
os.chdir(olddir)
raise
os.chdir(olddir)
+
+
+def patch_path(url, fetch, workdir, expand=True):
+ """Return the local path of a patch, or None if this isn't a patch"""
+
+ local = fetch.localpath(url)
+ base, ext = os.path.splitext(os.path.basename(local))
+ if ext in ('.gz', '.bz2', '.xz', '.Z'):
+ if expand:
+ local = os.path.join(workdir, base)
+ ext = os.path.splitext(base)[1]
+
+ urldata = fetch.ud[url]
+ if "apply" in urldata.parm:
+ apply = oe.types.boolean(urldata.parm["apply"])
+ if not apply:
+ return
+ elif ext not in (".diff", ".patch"):
+ return
+
+ return local
+
+def src_patches(d, all=False, expand=True):
+ workdir = d.getVar('WORKDIR')
+ fetch = bb.fetch2.Fetch([], d)
+ patches = []
+ sources = []
+ for url in fetch.urls:
+ local = patch_path(url, fetch, workdir, expand)
+ if not local:
+ if all:
+ local = fetch.localpath(url)
+ sources.append(local)
+ continue
+
+ urldata = fetch.ud[url]
+ parm = urldata.parm
+ patchname = parm.get('pname') or os.path.basename(local)
+
+ apply, reason = should_apply(parm, d)
+ if not apply:
+ if reason:
+ bb.note("Patch %s %s" % (patchname, reason))
+ continue
+
+ patchparm = {'patchname': patchname}
+ if "striplevel" in parm:
+ striplevel = parm["striplevel"]
+ elif "pnum" in parm:
+ #bb.msg.warn(None, "Deprecated usage of 'pnum' url parameter in '%s', please use 'striplevel'" % url)
+ striplevel = parm["pnum"]
+ else:
+ striplevel = '1'
+ patchparm['striplevel'] = striplevel
+
+ patchdir = parm.get('patchdir')
+ if patchdir:
+ patchparm['patchdir'] = patchdir
+
+ localurl = bb.fetch.encodeurl(('file', '', local, '', '', patchparm))
+ patches.append(localurl)
+
+ if all:
+ return sources
+
+ return patches
+
+
+def should_apply(parm, d):
+ if "mindate" in parm or "maxdate" in parm:
+ pn = d.getVar('PN')
+ srcdate = d.getVar('SRCDATE_%s' % pn)
+ if not srcdate:
+ srcdate = d.getVar('SRCDATE')
+
+ if srcdate == "now":
+ srcdate = d.getVar('DATE')
+
+ if "maxdate" in parm and parm["maxdate"] < srcdate:
+ return False, 'is outdated'
+
+ if "mindate" in parm and parm["mindate"] > srcdate:
+ return False, 'is predated'
+
+
+ if "minrev" in parm:
+ srcrev = d.getVar('SRCREV')
+ if srcrev and srcrev < parm["minrev"]:
+ return False, 'applies to later revisions'
+
+ if "maxrev" in parm:
+ srcrev = d.getVar('SRCREV')
+ if srcrev and srcrev > parm["maxrev"]:
+ return False, 'applies to earlier revisions'
+
+ if "rev" in parm:
+ srcrev = d.getVar('SRCREV')
+ if srcrev and parm["rev"] not in srcrev:
+ return False, "doesn't apply to revision"
+
+ if "notrev" in parm:
+ srcrev = d.getVar('SRCREV')
+ if srcrev and parm["notrev"] in srcrev:
+ return False, "doesn't apply to revision"
+
+ return True, None
+