angstrom: prefer the git version of tslib
[openembedded.git] / classes / newcollection.bbclass
blob9570597af0d65a5296981c983c4a4a7315eed18b
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
8 # time.
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):
14     deps = []
15     for task in (key for key in d.keys() if d.getVarFlag(key, "task")):
16         taskdeps = d.getVarFlag(task, "depends")
17         if taskdeps:
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
26     from bb import which
28     recipe = d.getVar("FILE", 1)
29     if not isabs(recipe):
30         return which(d.getVar("BBPATH", 1), recipe)
31     else:
32         return recipe
34 def __newcollection_get_recipedeps(d):
35     depdata = d.getVar("__depends", 1)
36     if not depdata:
37         return []
39     return [file for (file, rest) in depdata]
41 def __newcollection_get_fileuris(d):
42     from urlparse import urlparse, urlunparse
43     from glob import glob
44     from os.path import isabs, join, exists
46     files = []
47     for uri in d.getVar("SRC_URI", 1).split():
48         o = urlparse(uri)
49         if o[0] != "file":
50             continue
52         (scheme, netloc, path, params, query, frag) = o
54         if netloc:
55             path = netloc + path
57         try:
58             spath = path.split(";")
59             params = dict((part.split("=") for part in spath[1:]))
60             path = spath[0]
61         except ValueError:
62             params = {}
64         globbing = "*" in path
65         filespath = reversed(d.getVar("FILESPATH", True).split(":"))
66         for fp in filespath:
67             newpath = join(fp, path)
68             if globbing:
69                 globbed = filter(lambda f: exists(f), glob(newpath))
70                 files.extend(globbed)
71             else:
72                 if exists(newpath):
73                     files.append(newpath)
75     return files
77 def __newcollection_populate_file(src, dest, d):
78     import bb
79     from os.path import dirname, isdir, exists
80     from os import makedirs
81     from errno import EEXIST
82     from shutil import copytree, copy2
84     if not exists(src):
85         return
87     bb.mkdirhier(dirname(dest))
88     try:
89         if isdir(src):
90             copytree(src, dest, True)
91         else:
92             copy2(src, dest)
93     except (OSError, IOError), e:
94         bb.error("Unable to copy %s to %s:" % (src, dest))
95         bb.error(str(e))
96         return
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
105     from bb import debug
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 ""
115     if collectionsinfo:
116         collections = list(chain(*(glob(normpath(collection['path']))
117                                 for collection in collectionsinfo.itervalues())))
118     else:
119         topdir = d.getVar("TOPDIR", True)
120         collections = d.getVar("BBPATH", True).split(":")
121         if topdir in collections:
122             collections.remove(topdir)
124     if not collections:
125         return
127     files = filter(lambda f: any(f.startswith(c) for c in collections), files)
128     if not files:
129         return
131     destcol = d.getVar("NEWCOLLECTION", 1)
132     if not destcol:
133         raise FuncFailed("NEWCOLLECTION not defined, unable to populate new collection")
135     existingcollections = (d.getVar("EXISTINGCOLLECTIONS", 1) or "").split() + [destcol]
136     existing = []
137     for path in existingcollections:
138         pathurl = urlparse(path)
139         if pathurl[0]:
140                 existing += [collection_fetch(path,pathurl,d)]
141         else:
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:]
149         if not basefile:
150             continue
152         if any(exists(join(e, basefile)) for e in existing):
153             debug(1, "%s already in existing collections, skipping." % basefile)
154         else:
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
166 python () {
167     __newcollection_setup_taskdeps(d)