summaryrefslogtreecommitdiffstats
path: root/scripts/jhbuild/jhbuild2oe.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/jhbuild/jhbuild2oe.py')
-rwxr-xr-xscripts/jhbuild/jhbuild2oe.py278
1 files changed, 278 insertions, 0 deletions
diff --git a/scripts/jhbuild/jhbuild2oe.py b/scripts/jhbuild/jhbuild2oe.py
new file mode 100755
index 0000000000..ef292763de
--- /dev/null
+++ b/scripts/jhbuild/jhbuild2oe.py
@@ -0,0 +1,278 @@
1#!/usr/bin/env python
2# Available modulesets:
3#
4# bootstrap.modules
5# freedesktop.modules
6# gcj.modules
7# gnome-2.10.modules
8# gnome-2.12.modules
9# gnome-2.14.modules
10# gnome-2.16.modules
11# gnutls.modules
12# gtk28.modules
13# gtk.modules
14# xorg-7.0.modules
15# xorg.modules
16
17moduleset = 'xorg.modules'
18
19
20
21import cElementTree as ElementTree
22# import lxml.etree as ElementTree
23import re, os, bb, bb.data
24
25class Handlers(object):
26 """
27 Class to act as a store for handlers of jhbuild xml elements, and as a
28 dispatcher of parsed Elements to those handlers.
29
30 These handlers exist to take an xml element from the jhbuild files and
31 either produce bitbake metadata in self.packages, or produce data which
32 will be used by other element handlers to do so.
33
34 Handlers(filename) -> new object to parse and process jhbuild file of
35 name 'filename'.
36 """
37
38 cvsrootpat = re.compile(r'''
39 \s* # Skip leading whitespace
40 :(?P<scheme>[^:]+): # scheme (i.e. pserver, ext)
41 ((?P<user>\S+?)@)? # username
42 (?P<host>\S+?): # non-greedy match of the remote host
43 (?P<path>\S+) # remote path
44 ''', re.VERBOSE)
45
46
47 def __init__(self, msfile):
48 self.msfile = msfile
49 self.msbasename = os.path.basename(msfile)
50 self.msdirname = os.path.dirname(msfile)
51
52 self.handled = {}
53
54 self.cvsroots = {}
55 self.repositories = {}
56 self.packages = []
57
58 def handle(self, element, parent):
59 import sys
60 """
61 XML Element dispatch function. Can be called both from outside the
62 Handlers object to initiate handling, and from within individual XML
63 element handlers to ensure that dependent elements have been handled.
64
65 Does not handle a given XML Element more than once, as it retains
66 information about the handling state of the Elements it encounters.
67 """
68
69 try:
70 state = self.handled[element]
71 except KeyError:
72 pass
73 except:
74 return
75
76 try:
77 self.__class__.__dict__[element.tag](self, element, parent)
78 self.handled[element] = True
79 except KeyError:
80 self.handled[element] = False
81 sys.__stderr__.write('Unhandled element: %s\n' % element.tag)
82 except Exception:
83 sys.__stderr__.write('Error handling %s: %s:\n %s\n' % (element.tag, sys.exc_type, sys.exc_value))
84 self.handled[element] = False
85
86 print('handle(%s, %s) -> %s' % (element, parent, self.handled[element]))
87 return self.handled[element]
88
89 def cvsroot(self, element, parent):
90 # Rip apart the cvsroot style location to build a cvs:// url for
91 # bitbake's usage in the cvsmodule handler.
92 # root=":pserver:anoncvs@cvs.freedesktop.org:/cvs/fontconfig"
93 print("cvsroot(%s, %s)" % (element, parent))
94
95 root = element.attrib.get('root')
96 rootmatch = re.match(Handlers.cvsrootpat, root)
97 name = element.attrib.get('name')
98 user = rootmatch.group('user') or ''
99 if user != '':
100 pw = element.attrib.get('password') or ''
101 if pw != '':
102 pw = ':' + pw + '@'
103 else:
104 user = user + '@'
105 print('user: %s' % user)
106 print('pw: %s' % pw)
107
108 host = rootmatch.group('host')
109 print('host: %s' % host)
110 path = rootmatch.group('path') or '/'
111 print('path: %s' % path)
112
113 root = "cvs://%s%s%s%s" % (user, pw, host, path)
114 print('root: %s' % root)
115 self.cvsroots[name] = root
116
117 def cvsmodule(self, element, parent):
118 rootlist = [root for root in list(parent) if root.attrib.get('name') == element.attrib.get('cvsroot')]
119 if len(rootlist) < 1:
120 raise Exception("Error: cvsmodule '%s' requires cvsroot '%s'." % (element.attrib.get('module'), element.attrib.get('cvsroot')))
121
122 cvsroot = rootlist[0]
123
124
125 def include(self, element, parent):
126 href = element.attrib.get('href')
127 fullhref = os.path.join(self.msdirname, href)
128 tree = ElementTree.ElementTree(file=fullhref)
129 elem = tree.getroot()
130
131 # Append the children of the newly included root element to the parent
132 # element, and manually handle() them, as the currently running
133 # iteration isn't going to hit them.
134 for child in elem:
135 self.handle(child, elem)
136 parent.append(elem)
137
138 def repository(self, element, parent):
139 # TODO:
140 # Convert the URL in the href attribute, if necessary, to the format
141 # which bitbake expects to see in SRC_URI.
142 name = element.attrib.get('name')
143 self.repositories[name] = element.attrib.get('href')
144
145
146 def moduleset(self, element, parent):
147 for child in element:
148 self.handle(child, element)
149
150 def packagename(self, name):
151 # mangle name into an appropriate bitbake package name
152 return name.replace('/', '-')
153
154 def metamodule(self, element, parent):
155 # grab the deps
156 deps = None
157 for child in element:
158 if child.tag == 'dependencies':
159 deps = [self.packagename(dep.attrib.get('package')) for dep in child if dep.tag == "dep"]
160
161 # create the package
162 d = bb.data.init()
163 pn = self.packagename(element.attrib.get('id'))
164 bb.data.setVar('PN', pn, d)
165 bb.data.setVar('DEPENDS', ' '.join(deps), d)
166 bb.data.setVar('_handler', 'metamodule', d)
167 self.packages.append(d)
168
169 def autotools(self, element, parent):
170 deps = None
171 branch = None
172 for child in element:
173 if child.tag == 'dependencies':
174 deps = [self.packagename(dep.attrib.get('package')) for dep in child if dep.tag == "dep"]
175 elif child.tag == 'branch':
176 branch = child
177
178 # create the package
179 d = bb.data.init()
180 id = element.attrib.get('id')
181 if id is None:
182 raise Exception('Error: autotools element has no id attribute.')
183 pn = self.packagename(id)
184 bb.data.setVar('PN', pn, d)
185 if deps is not None:
186 bb.data.setVar('DEPENDS', ' '.join(deps), d)
187
188 if branch is not None:
189 # <branch repo="git.freedesktop.org" module="xorg/xserver"/>
190 repo = os.path.join(self.repositories[branch.attrib.get('repo')], branch.attrib.get('module'))
191 bb.data.setVar('SRC_URI', repo, d)
192
193 checkoutdir = branch.attrib.get('checkoutdir')
194 if checkoutdir is not None:
195 bb.data.setVar('S', os.path.join('${WORKDIR}', checkoutdir), d)
196
197 # build class
198 bb.data.setVar('INHERITS', 'autotools', d)
199 bb.data.setVarFlag('INHERITS', 'operator', '+=', d)
200 bb.data.setVar('_handler', 'autotools', d)
201 self.packages.append(d)
202
203class Emitter(object):
204 """
205 Class which contains a single method for the emission of a bitbake
206 package from the bitbake data produced by a Handlers object.
207 """
208
209 def __init__(self, filefunc = None, basedir = None):
210 def _defaultfilefunc(package):
211 # return a relative path to the bitbake .bb which will be written
212 return bb.data.getVar('PN', package, 1) + '.bb'
213
214 self.filefunc = filefunc or _defaultfilefunc
215 self.basedir = basedir or os.path.abspath(os.curdir)
216
217 def write(self, package, template = None):
218 # 1) Assemble new file contents in ram, either new from bitbake
219 # metadata, or a combination of the template and that metadata.
220 # 2) Open the path returned by the filefunc + the basedir for writing.
221 # 3) Write the new bitbake data file.
222 fdata = ''
223 if template:
224 f = file(template, 'r')
225 fdata = f.read()
226 f.close()
227
228 for key in bb.data.keys(package):
229 fdata = fdata.replace('@@'+key+'@@', bb.data.getVar(key, package))
230 else:
231 for key in bb.data.keys(package):
232 if key == '_handler':
233 continue
234 elif key == 'INHERITS':
235 fdata += 'inherit %s\n' % bb.data.getVar('INHERITS', package)
236 else:
237 oper = bb.data.getVarFlag(key, 'operator', package) or '='
238 fdata += '%s %s "%s"\n' % (key, oper, bb.data.getVar(key, package))
239
240 if not os.path.exists(os.path.join(self.basedir, os.path.dirname(self.filefunc(package)))):
241 os.makedirs(os.path.join(self.basedir, os.path.dirname(self.filefunc(package))))
242
243 out = file(os.path.join(self.basedir, self.filefunc(package)), 'w')
244 out.write(fdata)
245 out.close()
246
247def _test():
248 msfile = os.path.join(os.path.abspath(os.curdir), 'modulesets', moduleset)
249 tree = ElementTree.ElementTree(file=msfile)
250 elem = tree.getroot()
251
252 handlers = Handlers(msfile)
253 handlers.handle(elem, None)
254
255 def filefunc(package):
256 # return a relative path to the bitbake .bb which will be written
257 src_uri = bb.data.getVar('SRC_URI', package, 1)
258 filename = bb.data.getVar('PN', package, 1) + '.bb'
259 if not src_uri:
260 return filename
261 else:
262 substr = src_uri[src_uri.find('xorg/'):]
263 subdirlist = substr.split('/')[:2]
264 subdir = '-'.join(subdirlist)
265 return os.path.join(subdir, filename)
266
267 emitter = Emitter(filefunc)
268 for package in handlers.packages:
269 template = emitter.filefunc(package) + '.in'
270 if os.path.exists(template):
271 print("%s exists, emitting based on template" % template)
272 emitter.write(package, template)
273 else:
274 print("%s does not exist, emitting non-templated" % template)
275 emitter.write(package)
276
277if __name__ == "__main__":
278 _test()