summaryrefslogtreecommitdiffstats
path: root/meta/classes/patch.bbclass
diff options
context:
space:
mode:
Diffstat (limited to 'meta/classes/patch.bbclass')
-rw-r--r--meta/classes/patch.bbclass187
1 files changed, 187 insertions, 0 deletions
diff --git a/meta/classes/patch.bbclass b/meta/classes/patch.bbclass
new file mode 100644
index 0000000..86c65b3
--- /dev/null
+++ b/meta/classes/patch.bbclass
@@ -0,0 +1,187 @@
1# Copyright (C) 2006 OpenedHand LTD
2
3# Point to an empty file so any user's custom settings don't break things
4QUILTRCFILE ?= "${STAGING_ETCDIR_NATIVE}/quiltrc"
5
6PATCHDEPENDENCY = "${PATCHTOOL}-native:do_populate_sysroot"
7
8inherit terminal
9
10def src_patches(d, all = False ):
11 workdir = d.getVar('WORKDIR', True)
12 fetch = bb.fetch2.Fetch([], d)
13 patches = []
14 sources = []
15 for url in fetch.urls:
16 local = patch_path(url, fetch, workdir)
17 if not local:
18 if all:
19 local = fetch.localpath(url)
20 sources.append(local)
21 continue
22
23 urldata = fetch.ud[url]
24 parm = urldata.parm
25 patchname = parm.get('pname') or os.path.basename(local)
26
27 apply, reason = should_apply(parm, d)
28 if not apply:
29 if reason:
30 bb.note("Patch %s %s" % (patchname, reason))
31 continue
32
33 patchparm = {'patchname': patchname}
34 if "striplevel" in parm:
35 striplevel = parm["striplevel"]
36 elif "pnum" in parm:
37 #bb.msg.warn(None, "Deprecated usage of 'pnum' url parameter in '%s', please use 'striplevel'" % url)
38 striplevel = parm["pnum"]
39 else:
40 striplevel = '1'
41 patchparm['striplevel'] = striplevel
42
43 patchdir = parm.get('patchdir')
44 if patchdir:
45 patchparm['patchdir'] = patchdir
46
47 localurl = bb.fetch.encodeurl(('file', '', local, '', '', patchparm))
48 patches.append(localurl)
49
50 if all:
51 return sources
52
53 return patches
54
55def patch_path(url, fetch, workdir):
56 """Return the local path of a patch, or None if this isn't a patch"""
57
58 local = fetch.localpath(url)
59 base, ext = os.path.splitext(os.path.basename(local))
60 if ext in ('.gz', '.bz2', '.Z'):
61 local = os.path.join(workdir, base)
62 ext = os.path.splitext(base)[1]
63
64 urldata = fetch.ud[url]
65 if "apply" in urldata.parm:
66 apply = oe.types.boolean(urldata.parm["apply"])
67 if not apply:
68 return
69 elif ext not in (".diff", ".patch"):
70 return
71
72 return local
73
74def should_apply(parm, d):
75 """Determine if we should apply the given patch"""
76
77 if "mindate" in parm or "maxdate" in parm:
78 pn = d.getVar('PN', True)
79 srcdate = d.getVar('SRCDATE_%s' % pn, True)
80 if not srcdate:
81 srcdate = d.getVar('SRCDATE', True)
82
83 if srcdate == "now":
84 srcdate = d.getVar('DATE', True)
85
86 if "maxdate" in parm and parm["maxdate"] < srcdate:
87 return False, 'is outdated'
88
89 if "mindate" in parm and parm["mindate"] > srcdate:
90 return False, 'is predated'
91
92
93 if "minrev" in parm:
94 srcrev = d.getVar('SRCREV', True)
95 if srcrev and srcrev < parm["minrev"]:
96 return False, 'applies to later revisions'
97
98 if "maxrev" in parm:
99 srcrev = d.getVar('SRCREV', True)
100 if srcrev and srcrev > parm["maxrev"]:
101 return False, 'applies to earlier revisions'
102
103 if "rev" in parm:
104 srcrev = d.getVar('SRCREV', True)
105 if srcrev and parm["rev"] not in srcrev:
106 return False, "doesn't apply to revision"
107
108 if "notrev" in parm:
109 srcrev = d.getVar('SRCREV', True)
110 if srcrev and parm["notrev"] in srcrev:
111 return False, "doesn't apply to revision"
112
113 return True, None
114
115should_apply[vardepsexclude] = "DATE SRCDATE"
116
117python patch_do_patch() {
118 import oe.patch
119
120 patchsetmap = {
121 "patch": oe.patch.PatchTree,
122 "quilt": oe.patch.QuiltTree,
123 "git": oe.patch.GitApplyTree,
124 }
125
126 cls = patchsetmap[d.getVar('PATCHTOOL', True) or 'quilt']
127
128 resolvermap = {
129 "noop": oe.patch.NOOPResolver,
130 "user": oe.patch.UserResolver,
131 }
132
133 rcls = resolvermap[d.getVar('PATCHRESOLVE', True) or 'user']
134
135 classes = {}
136
137 s = d.getVar('S', True)
138
139 path = os.getenv('PATH')
140 os.putenv('PATH', d.getVar('PATH', True))
141
142 # We must use one TMPDIR per process so that the "patch" processes
143 # don't generate the same temp file name.
144
145 import tempfile
146 process_tmpdir = tempfile.mkdtemp()
147 os.environ['TMPDIR'] = process_tmpdir
148
149 for patch in src_patches(d):
150 _, _, local, _, _, parm = bb.fetch.decodeurl(patch)
151
152 if "patchdir" in parm:
153 patchdir = parm["patchdir"]
154 if not os.path.isabs(patchdir):
155 patchdir = os.path.join(s, patchdir)
156 else:
157 patchdir = s
158
159 if not patchdir in classes:
160 patchset = cls(patchdir, d)
161 resolver = rcls(patchset, oe_terminal)
162 classes[patchdir] = (patchset, resolver)
163 patchset.Clean()
164 else:
165 patchset, resolver = classes[patchdir]
166
167 bb.note("Applying patch '%s' (%s)" % (parm['patchname'], oe.path.format_display(local, d)))
168 try:
169 patchset.Import({"file":local, "strippath": parm['striplevel']}, True)
170 except Exception as exc:
171 bb.utils.remove(process_tmpdir, True)
172 bb.fatal(str(exc))
173 try:
174 resolver.Resolve()
175 except bb.BBHandledException as e:
176 bb.utils.remove(process_tmpdir, True)
177 bb.fatal(str(e))
178
179 bb.utils.remove(process_tmpdir, True)
180}
181patch_do_patch[vardepsexclude] = "PATCHRESOLVE"
182
183addtask patch after do_unpack
184do_patch[dirs] = "${WORKDIR}"
185do_patch[depends] = "${PATCHDEPENDENCY}"
186
187EXPORT_FUNCTIONS do_patch