collections.inc: add support for collection archives.
[openembedded.git] / conf / collections.inc
1 # Take a list of directories in COLLECTIONS, in priority order (highest to
2 # lowest), and use those to populate BBFILES, BBFILE_COLLECTIONS,
3 # BBFILE_PATTERN_*, and BBFILE_PRIORITY_*.  By default, COLLECTIONS is
4 # prepopulated with the locations the user specified in their BBPATH.
5 #
6 # Specifying an archive in COLLECTIONS is also supported.  Any archives of a
7 # supported format will be unpacked into COLLECTIONS_UNPACKDIR and used from
8 # there.
9
10 COLLECTIONS = "${@' '.join(d.getVar('BBPATH', 1).split(':'))}"
11 COLLECTIONS_UNPACKDIR = "${TMPDIR}/collections"
12
13 def collection_unpack(collection, name, d):
14     """ Unpack a collection archive and return the path to it. """
15     import bb
16     import os
17     from md5 import md5
18
19     handlers = {
20         ("tar"): "tar x --no-same-owner -f %s",
21         ("tar.gz", "tgz", "tar.Z"): "tar xz --no-same-owner -f %s",
22         ("tar.bz2", "tbz", "tbz2"): "tar xj --no-same-owner -f %s",
23         ("zip", "jar"): "unzip -q -o %s",
24     }
25
26     outpath = os.path.join(d.getVar("COLLECTIONS_UNPACKDIR", 1), name)
27
28     try:
29         collectiondata = open(collection, "r").read()
30     except IOError:
31         bb.fatal("Unable to open %s to calculate md5 sum" % collection)
32
33     md5obj = md5()
34     md5obj.update(collectiondata)
35     md5sum = md5obj.hexdigest()
36
37     md5file = os.path.join(outpath, "md5")
38     if os.path.exists(md5file):
39         try:
40             oldmd5sum = open(md5file).read()
41         except IOError:
42             pass
43         else:
44             if oldmd5sum == md5sum:
45                 bb.debug(1, "Using existing %s for collection %s" % (outpath, name))
46                 return outpath
47
48         bb.note("Removing old unpacked collection at %s" % outpath)
49         os.system("rm -rf %s" % outpath)
50
51     try:
52         cmd = (cmd for (exts, cmd) in handlers.iteritems()
53                    for e in exts
54                    if collection.endswith(e)).next()
55         cmd = "cd %s && PATH=\"%s\" %s" % (outpath, d.getVar("PATH", 1), cmd)
56     except StopIteration:
57         bb.fatal("Unable to find unpack handler for %s" % collection)
58
59     if not os.path.isdir(outpath):
60         os.makedirs(outpath)
61
62     bb.note("Unpacking %s to %s/" % (collection, outpath))
63     ret = os.system(cmd % collection)
64     if ret != 0:
65         bb.fatal("Unable to unpack %s" % collection)
66
67     md5out = open(md5file, "w")
68     md5out.write(md5sum)
69     md5out.close()
70     return outpath
71
72 def collections_setup(d):
73     """ Populate collection and bbfiles metadata from the COLLECTIONS var. """
74     import bb
75     import os
76     from itertools import izip, chain
77     from glob import glob
78
79     def setifunset(k, v):
80         if d.getVar(k, 0) is None:
81             d.setVar(k, v)
82
83     collections = d.getVar("COLLECTIONS", 1)
84     if not collections:
85         return
86     globbed = (glob(path) for path in collections.split())
87     collections = list(chain(*globbed))
88
89     collectionmap = {}
90     namemap = {}
91     for collection in collections:
92         basename = os.path.basename(collection).split(os.path.extsep)[0]
93         if namemap.get(basename):
94             basename = "%s-%s" % (basename, hash(collection))
95         namemap[basename] = collection
96         collectionmap[collection] = basename
97
98     for (collection, priority) in izip(collections, xrange(len(collections), 0, -1)):
99         if not os.path.exists(collection):
100             bb.fatal("Collection %s does not exist" % collection)
101
102         name = collectionmap[collection]
103         if not name:
104             bb.fatal("Unable to determine collection name for %s" % collection)
105
106         if not os.path.isdir(collection):
107             del collectionmap[collection]
108             unpacked = collection_unpack(collection, name, d)
109             if unpacked:
110                 collection = unpacked
111                 collectionmap[collection] = name
112             else:
113                 bb.fatal("Unable to unpack collection %s" % collection)
114
115         setifunset("BBFILE_PATTERN_%s" % name, "^%s/" % collection)
116         setifunset("BBFILE_PRIORITY_%s" % name, str(priority))
117
118     setifunset("BBFILE_COLLECTIONS", " ".join(collectionmap.values()))
119     setifunset("BBFILES", " ".join(collectionmap.keys()))
120
121 addhandler collections_eh
122 python collections_eh () {
123     from bb.event import getName
124
125     if getName(e) == "ConfigParsed":
126         collections_setup(e.data)
127
128     return NotHandled
129 }