1 # Copyright (c) 2009 MontaVista Software, Inc. All rights reserved.
3 # Released under the MIT license (see LICENSE.MIT for the terms)
5 # For a given provider, populate the recipe and associated files for it and its
6 # dependencies into a new collection from your existing ones. Great for extracting
7 # just the recipes you need from OpenEmbedded to do your work with a faster parse
11 # Ensure that newcollection is run on the dependencies pulled in by specific
12 # tasks (i.e. do_package_rpm[depends] = "rpm-native:do_populate_staging").
13 def __newcollection_setup_taskdeps(d):
15 for task in (key for key in d.keys() if d.getVarFlag(key, "task")):
16 taskdeps = d.getVarFlag(task, "depends")
18 items = (entry.split(":") for entry in taskdeps.split() if entry)
19 items = (entry for entry in items if len(entry) > 1)
20 deps.extend(("%s:do_newcollection" % dep for (dep, deptask) in items))
22 d.setVarFlag("do_newcollection_all", "depends", " ".join(deps))
24 def __newcollection_get_recipe(d):
25 from os.path import isabs
28 recipe = d.getVar("FILE", 1)
30 return which(d.getVar("BBPATH", 1), recipe)
34 def __newcollection_get_recipedeps(d):
35 depdata = d.getVar("__depends", 1)
39 return [file for (file, rest) in depdata]
41 def __newcollection_get_fileuris(d):
42 from urlparse import urlparse, urlunparse
44 from os.path import isabs, join, exists
47 for uri in d.getVar("SRC_URI", 1).split():
52 (scheme, netloc, path, params, query, frag) = o
58 spath = path.split(";")
59 params = dict((part.split("=") for part in spath[1:]))
64 globbing = "*" in path
65 filespath = reversed(d.getVar("FILESPATH", True).split(":"))
67 newpath = join(fp, path)
69 globbed = filter(lambda f: exists(f), glob(newpath))
77 def __newcollection_populate_file(src, dest, d):
79 from os.path import dirname, isdir, exists
80 from os import makedirs
81 from errno import EEXIST
82 from shutil import copytree, copy2
87 bb.mkdirhier(dirname(dest))
90 copytree(src, dest, True)
93 except (OSError, IOError), e:
94 bb.error("Unable to copy %s to %s:" % (src, dest))
98 bb.note("Copied %s to %s." % (src, dest))
101 python do_newcollection() {
102 from itertools import chain
103 from os.path import join, normpath, sep, exists
104 from glob import glob
106 from bb.build import FuncFailed
107 from urlparse import urlparse, urlunparse
109 files = set([__newcollection_get_recipe(d)])
110 files |= set(__newcollection_get_recipedeps(d))
111 files |= set(__newcollection_get_fileuris(d))
113 # filter out files that aren't in any overlays
114 collectionsinfo = d.getVar("COLLECTIONSINFO",1) or ""
116 collections = list(chain(*(glob(normpath(collection['path']))
117 for collection in collectionsinfo.itervalues())))
119 topdir = d.getVar("TOPDIR", True)
120 collections = d.getVar("BBPATH", True).split(":")
121 if topdir in collections:
122 collections.remove(topdir)
127 files = filter(lambda f: any(f.startswith(c) for c in collections), files)
131 destcol = d.getVar("NEWCOLLECTION", 1)
133 raise FuncFailed("NEWCOLLECTION not defined, unable to populate new collection")
135 existingcollections = (d.getVar("EXISTINGCOLLECTIONS", 1) or "").split() + [destcol]
137 for path in existingcollections:
138 pathurl = urlparse(path)
140 existing += [collection_fetch(path,pathurl,d)]
142 existing += glob(normpath(path))
144 for file in set(files):
145 for col in collections:
146 if file.startswith(col + sep):
147 basefile = file[len(col)+1:]
152 if any(exists(join(e, basefile)) for e in existing):
153 debug(1, "%s already in existing collections, skipping." % basefile)
155 __newcollection_populate_file(file, join(destcol, basefile), d)
157 do_newcollection[nostamp] = "1"
158 addtask newcollection
160 python do_newcollection_all () {
162 do_newcollection_all[nostamp] = "1"
163 do_newcollection_all[recrdeptask] = "do_newcollection"
164 addtask newcollection_all after do_newcollection
167 __newcollection_setup_taskdeps(d)