summaryrefslogtreecommitdiffstats
path: root/meta/classes/patch.bbclass
diff options
context:
space:
mode:
authorChris Larson <kergoth@openedhand.com>2006-08-28 20:36:36 +0000
committerChris Larson <kergoth@openedhand.com>2006-08-28 20:36:36 +0000
commitecb32bdee770c3ff6c73ac2a57e612872b13910f (patch)
treea97c3bb8b6fa3402c90510dab06f0f712667303e /meta/classes/patch.bbclass
parent01056cdbea9ebe38b589f74120f5fab39452bbf0 (diff)
downloadpoky-ecb32bdee770c3ff6c73ac2a57e612872b13910f.tar.gz
Patch failure handling updates, added a 'patch' concrete class, so we can apply patches to quilt-native itself.
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@670 311d38ba-8fff-0310-9ca6-ca027cbcb966
Diffstat (limited to 'meta/classes/patch.bbclass')
-rw-r--r--meta/classes/patch.bbclass237
1 files changed, 148 insertions, 89 deletions
diff --git a/meta/classes/patch.bbclass b/meta/classes/patch.bbclass
index 6616cb11a9..ea0182484e 100644
--- a/meta/classes/patch.bbclass
+++ b/meta/classes/patch.bbclass
@@ -1,9 +1,11 @@
1def patch_init(): 1# Copyright (C) 2006 OpenedHand LTD
2
3def patch_init(d):
2 import os, sys 4 import os, sys
3 5
4 def md5sum(fname): 6 def md5sum(fname):
5 import md5, sys 7 import md5, sys
6 8
7 f = file(fname, 'rb') 9 f = file(fname, 'rb')
8 m = md5.new() 10 m = md5.new()
9 while True: 11 while True:
@@ -13,12 +15,12 @@ def patch_init():
13 m.update(d) 15 m.update(d)
14 f.close() 16 f.close()
15 return m.hexdigest() 17 return m.hexdigest()
16 18
17 class CmdError(Exception): 19 class CmdError(Exception):
18 def __init__(self, exitstatus, output): 20 def __init__(self, exitstatus, output):
19 self.status = exitstatus 21 self.status = exitstatus
20 self.output = output 22 self.output = output
21 23
22 def __str__(self): 24 def __str__(self):
23 return "Command Error: exit status: %d Output:\n%s" % (self.status, self.output) 25 return "Command Error: exit status: %d Output:\n%s" % (self.status, self.output)
24 26
@@ -27,17 +29,17 @@ def patch_init():
27 self.path = path 29 self.path = path
28 def __str__(self): 30 def __str__(self):
29 return "Error: %s not found." % self.path 31 return "Error: %s not found." % self.path
30 32
31 def runcmd(args, dir = None): 33 def runcmd(args, dir = None):
32 import commands 34 import commands
33 35
34 if dir: 36 if dir:
35 olddir = os.path.abspath(os.curdir) 37 olddir = os.path.abspath(os.curdir)
36 if not os.path.exists(dir): 38 if not os.path.exists(dir):
37 raise NotFoundError(dir) 39 raise NotFoundError(dir)
38 os.chdir(dir) 40 os.chdir(dir)
39 # print("cwd: %s -> %s" % (olddir, self.dir)) 41 # print("cwd: %s -> %s" % (olddir, self.dir))
40 42
41 try: 43 try:
42 args = [ commands.mkarg(str(arg)) for arg in args ] 44 args = [ commands.mkarg(str(arg)) for arg in args ]
43 cmd = " ".join(args) 45 cmd = " ".join(args)
@@ -46,92 +48,143 @@ def patch_init():
46 if exitstatus != 0: 48 if exitstatus != 0:
47 raise CmdError(exitstatus >> 8, output) 49 raise CmdError(exitstatus >> 8, output)
48 return output 50 return output
49 51
50 finally: 52 finally:
51 if dir: 53 if dir:
52 os.chdir(olddir) 54 os.chdir(olddir)
53 55
54 class PatchError(Exception): 56 class PatchError(Exception):
55 def __init__(self, msg): 57 def __init__(self, msg):
56 self.msg = msg 58 self.msg = msg
57 59
58 def __str__(self): 60 def __str__(self):
59 return "Patch Error: %s" % self.msg 61 return "Patch Error: %s" % self.msg
60 62
61 import bb, bb.data, bb.fetch 63 import bb, bb.data, bb.fetch
62 64
63 class PatchSet(object): 65 class PatchSet(object):
64 defaults = { 66 defaults = {
65 "strippath": 1 67 "strippath": 1
66 } 68 }
67 69
68 def __init__(self, dir, d): 70 def __init__(self, dir, d):
69 self.dir = dir 71 self.dir = dir
70 self.d = d 72 self.d = d
71 self.patches = [] 73 self.patches = []
72 self._current = None 74 self._current = None
73 75
74 def current(self): 76 def current(self):
75 return self._current 77 return self._current
76 78
77 def Clean(self): 79 def Clean(self):
78 """ 80 """
79 Clean out the patch set. Generally includes unapplying all 81 Clean out the patch set. Generally includes unapplying all
80 patches and wiping out all associated metadata. 82 patches and wiping out all associated metadata.
81 """ 83 """
82 raise NotImplementedError() 84 raise NotImplementedError()
83 85
84 def Import(self, patch, force): 86 def Import(self, patch, force):
85 if not patch.get("file"): 87 if not patch.get("file"):
86 if not patch.get("remote"): 88 if not patch.get("remote"):
87 raise PatchError("Patch file must be specified in patch import.") 89 raise PatchError("Patch file must be specified in patch import.")
88 else: 90 else:
89 patch["file"] = bb.fetch.localpath(patch["remote"], self.d) 91 patch["file"] = bb.fetch.localpath(patch["remote"], self.d)
90 92
91 for param in PatchSet.defaults: 93 for param in PatchSet.defaults:
92 if not patch.get(param): 94 if not patch.get(param):
93 patch[param] = PatchSet.defaults[param] 95 patch[param] = PatchSet.defaults[param]
94 96
95 if patch.get("remote"): 97 if patch.get("remote"):
96 patch["file"] = bb.data.expand(bb.fetch.localpath(patch["remote"], self.d), self.d) 98 patch["file"] = bb.data.expand(bb.fetch.localpath(patch["remote"], self.d), self.d)
97 99
98 patch["filemd5"] = md5sum(patch["file"]) 100 patch["filemd5"] = md5sum(patch["file"])
99 101
100 def Push(self, force): 102 def Push(self, force):
101 raise NotImplementedError() 103 raise NotImplementedError()
102 104
103 def Pop(self, force): 105 def Pop(self, force):
104 raise NotImplementedError() 106 raise NotImplementedError()
105 107
106 def Refresh(self, remote = None, all = None): 108 def Refresh(self, remote = None, all = None):
107 raise NotImplementedError() 109 raise NotImplementedError()
108 110
109 111
112 class PatchTree(PatchSet):
113 def __init__(self, dir, d):
114 PatchSet.__init__(self, dir, d)
115
116 def Import(self, patch, force = None):
117 """"""
118 PatchSet.Import(self, patch, force)
119
120 self.patches.insert(self._current or 0, patch)
121
122 def _applypatch(self, patch, force = None, reverse = None):
123 shellcmd = ["patch", "<", patch['file'], "-p", patch['strippath']]
124 if reverse:
125 shellcmd.append('-R')
126 shellcmd.append('--dry-run')
127
128 try:
129 output = runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
130 except CmdError:
131 if force:
132 shellcmd.pop(len(shellcmd) - 1)
133 output = runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
134 else:
135 import sys
136 raise sys.exc_value
137
138 return output
139
140 def Push(self, force = None, all = None):
141 if all:
142 for i in self.patches:
143 if self._current is not None:
144 self._current = self._current + 1
145 else:
146 self._current = 0
147 self._applypatch(i, force)
148 else:
149 if self._current is not None:
150 self._current = self._current + 1
151 else:
152 self._current = 0
153 self._applypatch(self.patches[self._current], force)
154
155
156 def Pop(self, force = None, all = None):
157 if all:
158 for i in self.patches:
159 self._applypatch(i, force, True)
160 else:
161 self._applypatch(self.patches[self._current], force, True)
162
163 def Clean(self):
164 """"""
165
110 class QuiltTree(PatchSet): 166 class QuiltTree(PatchSet):
111 def _runcmd(self, args): 167 def _runcmd(self, args):
112 runcmd(["quilt"] + args, self.dir) 168 runcmd(["quilt"] + args, self.dir)
113 169
114 def _quiltpatchpath(self, file): 170 def _quiltpatchpath(self, file):
115 return os.path.join(self.dir, "patches", os.path.basename(file)) 171 return os.path.join(self.dir, "patches", os.path.basename(file))
116 172
117 173
118 def __init__(self, dir, d): 174 def __init__(self, dir, d):
119 PatchSet.__init__(self, dir, d) 175 PatchSet.__init__(self, dir, d)
120 self.initialized = False 176 self.initialized = False
121 177
122 def Clean(self): 178 def Clean(self):
123 try: 179 try:
124 self._runcmd(["pop", "-a", "-f"]) 180 self._runcmd(["pop", "-a", "-f"])
125 except CmdError: 181 except CmdError:
126 if sys.exc_value.output.strip() == "No patch removed": 182 pass
127 pass
128 else:
129 raise PatchError("Unable to clean patches from tree:\n"+str(sys.exc_value))
130 except NotFoundError: 183 except NotFoundError:
131 pass 184 pass
132 runcmd(["rm", "-rf", os.path.join(self.dir, "patches"), os.path.join(self.dir, ".pc")]) 185 # runcmd(["rm", "-rf", os.path.join(self.dir, "patches"), os.path.join(self.dir, ".pc")])
133 self.initialized = True 186 self.initialized = True
134 187
135 def InitFromDir(self): 188 def InitFromDir(self):
136 # read series -> self.patches 189 # read series -> self.patches
137 seriespath = os.path.join(self.dir, 'patches', 'series') 190 seriespath = os.path.join(self.dir, 'patches', 'series')
@@ -148,7 +201,7 @@ def patch_init():
148 patch["strippath"] = parts[1][2:] 201 patch["strippath"] = parts[1][2:]
149 self.patches.append(patch) 202 self.patches.append(patch)
150 series.close() 203 series.close()
151 204
152 # determine which patches are applied -> self._current 205 # determine which patches are applied -> self._current
153 try: 206 try:
154 output = runcmd(["quilt", "applied"], self.dir) 207 output = runcmd(["quilt", "applied"], self.dir)
@@ -162,45 +215,45 @@ def patch_init():
162 if os.path.basename(patch["quiltfile"]) == output[-1]: 215 if os.path.basename(patch["quiltfile"]) == output[-1]:
163 self._current = self.patches.index(patch) 216 self._current = self.patches.index(patch)
164 self.initialized = True 217 self.initialized = True
165 218
166 def Import(self, patch, force = None): 219 def Import(self, patch, force = None):
167 if not self.initialized: 220 if not self.initialized:
168 self.InitFromDir() 221 self.InitFromDir()
169 PatchSet.Import(self, patch, force) 222 PatchSet.Import(self, patch, force)
170 223
171 args = ["import", "-p", patch["strippath"]] 224 args = ["import", "-p", patch["strippath"]]
172 if force: 225 if force:
173 args.append("-f") 226 args.append("-f")
174 args.append(patch["file"]) 227 args.append(patch["file"])
175 228
176 self._runcmd(args) 229 self._runcmd(args)
177 230
178 patch["quiltfile"] = self._quiltpatchpath(patch["file"]) 231 patch["quiltfile"] = self._quiltpatchpath(patch["file"])
179 patch["quiltfilemd5"] = md5sum(patch["quiltfile"]) 232 patch["quiltfilemd5"] = md5sum(patch["quiltfile"])
180 233
181 # TODO: determine if the file being imported: 234 # TODO: determine if the file being imported:
182 # 1) is already imported, and is the same 235 # 1) is already imported, and is the same
183 # 2) is already imported, but differs 236 # 2) is already imported, but differs
184 237
185 self.patches.insert(self._current or 0, patch) 238 self.patches.insert(self._current or 0, patch)
186 239
187 240
188 def Push(self, force = None, all = None): 241 def Push(self, force = None, all = None):
189 # quilt push [-f] 242 # quilt push [-f]
190 243
191 args = ["push"] 244 args = ["push"]
192 if force: 245 if force:
193 args.append("-f") 246 args.append("-f")
194 if all: 247 if all:
195 args.append("-a") 248 args.append("-a")
196 249
197 self._runcmd(args) 250 self._runcmd(args)
198 251
199 if self._current is not None: 252 if self._current is not None:
200 self._current = self._current + 1 253 self._current = self._current + 1
201 else: 254 else:
202 self._current = 0 255 self._current = 0
203 256
204 def Pop(self, force = None, all = None): 257 def Pop(self, force = None, all = None):
205 # quilt pop [-f] 258 # quilt pop [-f]
206 args = ["pop"] 259 args = ["pop"]
@@ -208,15 +261,15 @@ def patch_init():
208 args.append("-f") 261 args.append("-f")
209 if all: 262 if all:
210 args.append("-a") 263 args.append("-a")
211 264
212 self._runcmd(args) 265 self._runcmd(args)
213 266
214 if self._current == 0: 267 if self._current == 0:
215 self._current = None 268 self._current = None
216 269
217 if self._current is not None: 270 if self._current is not None:
218 self._current = self._current - 1 271 self._current = self._current - 1
219 272
220 def Refresh(self, **kwargs): 273 def Refresh(self, **kwargs):
221 if kwargs.get("remote"): 274 if kwargs.get("remote"):
222 patch = self.patches[kwargs["patch"]] 275 patch = self.patches[kwargs["patch"]]
@@ -227,7 +280,7 @@ def patch_init():
227 import shutil 280 import shutil
228 if not patch.get("file") and patch.get("remote"): 281 if not patch.get("file") and patch.get("remote"):
229 patch["file"] = bb.fetch.localpath(patch["remote"], self.d) 282 patch["file"] = bb.fetch.localpath(patch["remote"], self.d)
230 283
231 shutil.copyfile(patch["quiltfile"], patch["file"]) 284 shutil.copyfile(patch["quiltfile"], patch["file"])
232 else: 285 else:
233 raise PatchError("Unable to do a remote refresh of %s, unsupported remote url scheme %s." % (os.path.basename(patch["quiltfile"]), type)) 286 raise PatchError("Unable to do a remote refresh of %s, unsupported remote url scheme %s." % (os.path.basename(patch["quiltfile"]), type))
@@ -239,31 +292,31 @@ def patch_init():
239 elif kwargs.get("patch"): 292 elif kwargs.get("patch"):
240 args.append(os.path.basename(self.patches[kwargs["patch"]]["quiltfile"])) 293 args.append(os.path.basename(self.patches[kwargs["patch"]]["quiltfile"]))
241 self._runcmd(args) 294 self._runcmd(args)
242 295
243 class Resolver(object): 296 class Resolver(object):
244 def __init__(self, patchset): 297 def __init__(self, patchset):
245 raise NotImplementedError() 298 raise NotImplementedError()
246 299
247 def Resolve(self): 300 def Resolve(self):
248 raise NotImplementedError() 301 raise NotImplementedError()
249 302
250 def Revert(self): 303 def Revert(self):
251 raise NotImplementedError() 304 raise NotImplementedError()
252 305
253 def Finalize(self): 306 def Finalize(self):
254 raise NotImplementedError() 307 raise NotImplementedError()
255 308
256 # Patch resolver which relies on the user doing all the work involved in the 309 # Patch resolver which relies on the user doing all the work involved in the
257 # resolution, with the exception of refreshing the remote copy of the patch 310 # resolution, with the exception of refreshing the remote copy of the patch
258 # files (the urls). 311 # files (the urls).
259 class UserResolver(Resolver): 312 class UserResolver(Resolver):
260 def __init__(self, patchset): 313 def __init__(self, patchset):
261 self.patchset = patchset 314 self.patchset = patchset
262 315
263 # Force a push in the patchset, then drop to a shell for the user to 316 # Force a push in the patchset, then drop to a shell for the user to
264 # resolve any rejected hunks 317 # resolve any rejected hunks
265 def Resolve(self): 318 def Resolve(self):
266 319
267 olddir = os.path.abspath(os.curdir) 320 olddir = os.path.abspath(os.curdir)
268 os.chdir(self.patchset.dir) 321 os.chdir(self.patchset.dir)
269 try: 322 try:
@@ -274,21 +327,21 @@ def patch_init():
274 return 327 return
275 print(sys.exc_value) 328 print(sys.exc_value)
276 print('NOTE: dropping user into a shell, so that patch rejects can be fixed manually.') 329 print('NOTE: dropping user into a shell, so that patch rejects can be fixed manually.')
277 330
278 os.system('/bin/sh') 331 os.system('/bin/sh')
279 332
280 # Construct a new PatchSet after the user's changes, compare the 333 # Construct a new PatchSet after the user's changes, compare the
281 # sets, checking patches for modifications, and doing a remote 334 # sets, checking patches for modifications, and doing a remote
282 # refresh on each. 335 # refresh on each.
283 oldpatchset = self.patchset 336 oldpatchset = self.patchset
284 self.patchset = oldpatchset.__class__(self.patchset.dir, self.patchset.d) 337 self.patchset = oldpatchset.__class__(self.patchset.dir, self.patchset.d)
285 338
286 for patch in self.patchset.patches: 339 for patch in self.patchset.patches:
287 oldpatch = None 340 oldpatch = None
288 for opatch in oldpatchset.patches: 341 for opatch in oldpatchset.patches:
289 if opatch["quiltfile"] == patch["quiltfile"]: 342 if opatch["quiltfile"] == patch["quiltfile"]:
290 oldpatch = opatch 343 oldpatch = opatch
291 344
292 if oldpatch: 345 if oldpatch:
293 patch["remote"] = oldpatch["remote"] 346 patch["remote"] = oldpatch["remote"]
294 if patch["quiltfile"] == oldpatch["quiltfile"]: 347 if patch["quiltfile"] == oldpatch["quiltfile"]:
@@ -303,17 +356,18 @@ def patch_init():
303 os.chdir(olddir) 356 os.chdir(olddir)
304 raise 357 raise
305 os.chdir(olddir) 358 os.chdir(olddir)
306 359
307 # Throw away the changes to the patches in the patchset made by resolve() 360 # Throw away the changes to the patches in the patchset made by resolve()
308 def Revert(self): 361 def Revert(self):
309 raise NotImplementedError() 362 raise NotImplementedError()
310 363
311 # Apply the changes to the patches in the patchset made by resolve() 364 # Apply the changes to the patches in the patchset made by resolve()
312 def Finalize(self): 365 def Finalize(self):
313 raise NotImplementedError() 366 raise NotImplementedError()
314 367
315 g = globals() 368 g = globals()
316 g["PatchSet"] = PatchSet 369 g["PatchSet"] = PatchSet
370 g["PatchTree"] = PatchTree
317 g["QuiltTree"] = QuiltTree 371 g["QuiltTree"] = QuiltTree
318 g["Resolver"] = Resolver 372 g["Resolver"] = Resolver
319 g["UserResolver"] = UserResolver 373 g["UserResolver"] = UserResolver
@@ -322,45 +376,48 @@ def patch_init():
322 376
323addtask patch after do_unpack 377addtask patch after do_unpack
324do_patch[dirs] = "${WORKDIR}" 378do_patch[dirs] = "${WORKDIR}"
325python base_do_patch() { 379python patch_do_patch() {
326 import re 380 import re
327 import bb.fetch 381 import bb.fetch
328 382
329 patch_init() 383 patch_init(d)
330 384
331 src_uri = (bb.data.getVar('SRC_URI', d, 1) or '').split() 385 src_uri = (bb.data.getVar('SRC_URI', d, 1) or '').split()
332 if not src_uri: 386 if not src_uri:
333 return 387 return
334 388
335 patchsetmap = { 389 patchsetmap = {
390 "patch": PatchTree,
336 "quilt": QuiltTree, 391 "quilt": QuiltTree,
337 } 392 }
338 393
339 cls = patchsetmap[bb.data.getVar('PATCHTOOL', d, 1) or 'quilt'] 394 cls = patchsetmap[bb.data.getVar('PATCHTOOL', d, 1) or 'quilt']
340 395
341 resolvermap = { 396 resolvermap = {
342 "user": UserResolver, 397 "user": UserResolver,
343 } 398 }
344 399
345 rcls = resolvermap[bb.data.getVar('PATCHRESOLVE', d, 1) or 'user'] 400 rcls = resolvermap[bb.data.getVar('PATCHRESOLVE', d, 1) or 'user']
346 401
347 s = bb.data.getVar('S', d, 1) 402 s = bb.data.getVar('S', d, 1)
348 403
404 path = os.getenv('PATH')
405 os.putenv('PATH', bb.data.getVar('PATH', d, 1))
349 patchset = cls(s, d) 406 patchset = cls(s, d)
350 patchset.Clean() 407 patchset.Clean()
351 408
352 resolver = rcls(patchset) 409 resolver = rcls(patchset)
353 410
354 workdir = bb.data.getVar('WORKDIR', d, 1) 411 workdir = bb.data.getVar('WORKDIR', d, 1)
355 for url in src_uri: 412 for url in src_uri:
356 (type, host, path, user, pswd, parm) = bb.decodeurl(url) 413 (type, host, path, user, pswd, parm) = bb.decodeurl(url)
357 if not "patch" in parm: 414 if not "patch" in parm:
358 continue 415 continue
359 416
360 bb.fetch.init([url],d) 417 bb.fetch.init([url],d)
361 url = bb.encodeurl((type, host, path, user, pswd, [])) 418 url = bb.encodeurl((type, host, path, user, pswd, []))
362 local = os.path.join('/', bb.fetch.localpath(url, d)) 419 local = os.path.join('/', bb.fetch.localpath(url, d))
363 420
364 # did it need to be unpacked? 421 # did it need to be unpacked?
365 dots = os.path.basename(local).split(".") 422 dots = os.path.basename(local).split(".")
366 if dots[-1] in ['gz', 'bz2', 'Z']: 423 if dots[-1] in ['gz', 'bz2', 'Z']:
@@ -368,45 +425,45 @@ python base_do_patch() {
368 else: 425 else:
369 unpacked = local 426 unpacked = local
370 unpacked = bb.data.expand(unpacked, d) 427 unpacked = bb.data.expand(unpacked, d)
371 428
372 if "pnum" in parm: 429 if "pnum" in parm:
373 pnum = parm["pnum"] 430 pnum = parm["pnum"]
374 else: 431 else:
375 pnum = "1" 432 pnum = "1"
376 433
377 if "pname" in parm: 434 if "pname" in parm:
378 pname = parm["pname"] 435 pname = parm["pname"]
379 else: 436 else:
380 pname = os.path.basename(unpacked) 437 pname = os.path.basename(unpacked)
381 438
382 if "mindate" in parm: 439 if "mindate" in parm:
383 mindate = parm["mindate"] 440 mindate = parm["mindate"]
384 else: 441 else:
385 mindate = 0 442 mindate = 0
386 443
387 if "maxdate" in parm: 444 if "maxdate" in parm:
388 maxdate = parm["maxdate"] 445 maxdate = parm["maxdate"]
389 else: 446 else:
390 maxdate = "20711226" 447 maxdate = "20711226"
391 448
392 pn = bb.data.getVar('PN', d, 1) 449 pn = bb.data.getVar('PN', d, 1)
393 srcdate = bb.data.getVar('SRCDATE_%s' % pn, d, 1) 450 srcdate = bb.data.getVar('SRCDATE_%s' % pn, d, 1)
394 451
395 if not srcdate: 452 if not srcdate:
396 srcdate = bb.data.getVar('SRCDATE', d, 1) 453 srcdate = bb.data.getVar('SRCDATE', d, 1)
397 454
398 if srcdate == "now": 455 if srcdate == "now":
399 srcdate = bb.data.getVar('DATE', d, 1) 456 srcdate = bb.data.getVar('DATE', d, 1)
400 457
401 if (maxdate < srcdate) or (mindate > srcdate): 458 if (maxdate < srcdate) or (mindate > srcdate):
402 if (maxdate < srcdate): 459 if (maxdate < srcdate):
403 bb.note("Patch '%s' is outdated" % pname) 460 bb.note("Patch '%s' is outdated" % pname)
404 461
405 if (mindate > srcdate): 462 if (mindate > srcdate):
406 bb.note("Patch '%s' is predated" % pname) 463 bb.note("Patch '%s' is predated" % pname)
407 464
408 continue 465 continue
409 466
410 bb.note("Applying patch '%s'" % pname) 467 bb.note("Applying patch '%s'" % pname)
411 try: 468 try:
412 patchset.Import({"file":unpacked, "remote":url, "strippath": pnum}, True) 469 patchset.Import({"file":unpacked, "remote":url, "strippath": pnum}, True)
@@ -415,3 +472,5 @@ python base_do_patch() {
415 raise bb.build.FuncFailed(str(sys.exc_value)) 472 raise bb.build.FuncFailed(str(sys.exc_value))
416 resolver.Resolve() 473 resolver.Resolve()
417} 474}
475
476EXPORT_FUNCTIONS do_patch