summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/ui/crumbs/configurator.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/ui/crumbs/configurator.py')
-rw-r--r--bitbake/lib/bb/ui/crumbs/configurator.py346
1 files changed, 0 insertions, 346 deletions
diff --git a/bitbake/lib/bb/ui/crumbs/configurator.py b/bitbake/lib/bb/ui/crumbs/configurator.py
deleted file mode 100644
index 837ee1ca91..0000000000
--- a/bitbake/lib/bb/ui/crumbs/configurator.py
+++ /dev/null
@@ -1,346 +0,0 @@
1#
2# BitBake Graphical GTK User Interface
3#
4# Copyright (C) 2011 Intel Corporation
5#
6# Authored by Joshua Lock <josh@linux.intel.com>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License version 2 as
10# published by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program; if not, write to the Free Software Foundation, Inc.,
19# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21import gobject
22import copy
23import re, os
24from bb import data
25
26class Configurator(gobject.GObject):
27
28 """
29 A GObject to handle writing modified configuration values back
30 to conf files.
31 """
32 __gsignals__ = {
33 "layers-loaded" : (gobject.SIGNAL_RUN_LAST,
34 gobject.TYPE_NONE,
35 ()),
36 "layers-changed" : (gobject.SIGNAL_RUN_LAST,
37 gobject.TYPE_NONE,
38 ())
39 }
40
41 def __init__(self):
42 gobject.GObject.__init__(self)
43 self.bblayers = None
44 self.enabled_layers = {}
45 self.loaded_layers = {}
46 self.config = {}
47 self.orig_config = {}
48 self.preconf = None
49 self.postconf = None
50
51 # NOTE: cribbed from the cooker...
52 def _parse(self, f, data, include=False):
53 try:
54 return bb.parse.handle(f, data, include)
55 except (IOError, bb.parse.ParseError) as exc:
56 parselog.critical("Unable to parse %s: %s" % (f, exc))
57 sys.exit(1)
58
59 def _loadConf(self, path):
60 def getString(var):
61 return data.getVar(var, True) or ""
62
63 if self.orig_config:
64 del self.orig_config
65 self.orig_config = {}
66
67 data = bb.data.init()
68 data = self._parse(path, data)
69
70 # We only need to care about certain variables
71 mach = getString('MACHINE')
72 if mach and mach != self.config.get('MACHINE', ''):
73 self.config['MACHINE'] = mach
74 sdkmach = getString('SDKMACHINE')
75 if sdkmach and sdkmach != self.config.get('SDKMACHINE', ''):
76 self.config['SDKMACHINE'] = sdkmach
77 distro = getString('DISTRO')
78 if not distro:
79 distro = "defaultsetup"
80 if distro and distro != self.config.get('DISTRO', ''):
81 self.config['DISTRO'] = distro
82 bbnum = getString('BB_NUMBER_THREADS')
83 if bbnum and bbnum != self.config.get('BB_NUMBER_THREADS', ''):
84 self.config['BB_NUMBER_THREADS'] = bbnum
85 pmake = getString('PARALLEL_MAKE')
86 if pmake and pmake != self.config.get('PARALLEL_MAKE', ''):
87 self.config['PARALLEL_MAKE'] = pmake
88 pclass = getString('PACKAGE_CLASSES')
89 if pclass and pclass != self.config.get('PACKAGE_CLASSES', ''):
90 self.config['PACKAGE_CLASSES'] = pclass
91 fstypes = getString('IMAGE_FSTYPES')
92 if fstypes and fstypes != self.config.get('IMAGE_FSTYPES', ''):
93 self.config['IMAGE_FSTYPES'] = fstypes
94
95 # Values which aren't always set in the conf must be explicitly
96 # loaded as empty values for save to work
97 incompat = getString('INCOMPATIBLE_LICENSE')
98 if incompat and incompat != self.config.get('INCOMPATIBLE_LICENSE', ''):
99 self.config['INCOMPATIBLE_LICENSE'] = incompat
100 else:
101 self.config['INCOMPATIBLE_LICENSE'] = ""
102
103 # Non-standard, namespaces, variables for GUI preferences
104 toolchain = getString('HOB_BUILD_TOOLCHAIN')
105 if toolchain and toolchain != self.config.get('HOB_BUILD_TOOLCHAIN', ''):
106 self.config['HOB_BUILD_TOOLCHAIN'] = toolchain
107 header = getString('HOB_BUILD_TOOLCHAIN_HEADERS')
108 if header and header != self.config.get('HOB_BUILD_TOOLCHAIN_HEADERS', ''):
109 self.config['HOB_BUILD_TOOLCHAIN_HEADERS'] = header
110
111 self.orig_config = copy.deepcopy(self.config)
112
113 def setConfVar(self, var, val):
114 self.config[var] = val
115
116 def getConfVar(self, var):
117 if var in self.config:
118 return self.config[var]
119 else:
120 return ""
121
122 def _loadLayerConf(self, path):
123 self.bblayers = path
124 self.enabled_layers = {}
125 self.loaded_layers = {}
126 data = bb.data.init()
127 data = self._parse(self.bblayers, data)
128 layers = (data.getVar('BBLAYERS', True) or "").split()
129 for layer in layers:
130 # TODO: we may be better off calling the layer by its
131 # BBFILE_COLLECTIONS value?
132 name = self._getLayerName(layer)
133 self.loaded_layers[name] = layer
134
135 self.enabled_layers = copy.deepcopy(self.loaded_layers)
136 self.emit("layers-loaded")
137
138 def _addConfigFile(self, path):
139 conffiles = ["local.conf", "hob-pre.conf", "hob-post.conf"]
140 pref, sep, filename = path.rpartition("/")
141
142 if filename == "hob-pre.conf":
143 self.preconf = path
144
145 if filename == "hob-post.conf":
146 self.postconf = path
147
148 if filename in conffiles:
149 self._loadConf(path)
150 elif filename == "bblayers.conf":
151 self._loadLayerConf(path)
152
153 def _splitLayer(self, path):
154 # we only care about the path up to /conf/layer.conf
155 layerpath, conf, end = path.rpartition("/conf/")
156 return layerpath
157
158 def _getLayerName(self, path):
159 # Should this be the collection name?
160 layerpath, sep, name = path.rpartition("/")
161 return name
162
163 def disableLayer(self, layer):
164 if layer in self.enabled_layers:
165 del self.enabled_layers[layer]
166
167 def addLayerConf(self, confpath):
168 layerpath = self._splitLayer(confpath)
169 name = self._getLayerName(layerpath)
170
171 if not layerpath or not name:
172 return None, None
173 elif name not in self.enabled_layers:
174 self.addLayer(name, layerpath)
175 return name, layerpath
176 else:
177 return name, None
178
179 def addLayer(self, name, path):
180 self.enabled_layers[name] = path
181
182 def _isLayerConfDirty(self):
183 # if a different number of layers enabled to what was
184 # loaded, definitely different
185 if len(self.enabled_layers) != len(self.loaded_layers):
186 return True
187
188 for layer in self.loaded_layers:
189 # if layer loaded but no longer present, definitely dirty
190 if layer not in self.enabled_layers:
191 return True
192
193 for layer in self.enabled_layers:
194 # if this layer wasn't present at load, definitely dirty
195 if layer not in self.loaded_layers:
196 return True
197 # if this layers path has changed, definitely dirty
198 if self.enabled_layers[layer] != self.loaded_layers[layer]:
199 return True
200
201 return False
202
203 def _constructLayerEntry(self):
204 """
205 Returns a string representing the new layer selection
206 """
207 layers = self.enabled_layers.copy()
208 # Construct BBLAYERS entry
209 layer_entry = "BBLAYERS = \" \\\n"
210 if 'meta' in layers:
211 layer_entry = layer_entry + " %s \\\n" % layers['meta']
212 del layers['meta']
213 for layer in layers:
214 layer_entry = layer_entry + " %s \\\n" % layers[layer]
215 layer_entry = layer_entry + " \""
216
217 return "".join(layer_entry)
218
219 def writeConfFile(self, conffile, contents):
220 """
221 Make a backup copy of conffile and write a new file in its stead with
222 the lines in the contents list.
223 """
224 # Create a backup of the conf file
225 bkup = "%s~" % conffile
226 os.rename(conffile, bkup)
227
228 # Write the contents list object to the conf file
229 with open(conffile, "w") as new:
230 new.write("".join(contents))
231
232 def updateConf(self, orig_lines, changed_values):
233 new_config_lines = []
234 for var in changed_values:
235 # Convenience function for re.subn(). If the pattern matches
236 # return a string which contains an assignment using the same
237 # assignment operator as the old assignment.
238 def replace_val(matchobj):
239 var = matchobj.group(1) # config variable
240 op = matchobj.group(2) # assignment operator
241 val = changed_values[var] # new config value
242 return "%s %s \"%s\"" % (var, op, val)
243
244 pattern = '^\s*(%s)\s*([+=?.]+)(.*)' % re.escape(var)
245 p = re.compile(pattern)
246 cnt = 0
247 replaced = False
248
249 # Iterate over the local.conf lines and if they are a match
250 # for the pattern comment out the line and append a new line
251 # with the new VAR op "value" entry
252 for line in orig_lines:
253 new_line, replacements = p.subn(replace_val, line)
254 if replacements:
255 orig_lines[cnt] = "#%s" % line
256 new_config_lines.append(new_line)
257 replaced = True
258 cnt = cnt + 1
259
260 if not replaced:
261 new_config_lines.append("%s = \"%s\"\n" % (var, changed_values[var]))
262
263 # Add the modified variables
264 orig_lines.extend(new_config_lines)
265 return orig_lines
266
267 def writeConf(self):
268 pre_vars = ["MACHINE", "SDKMACHINE", "DISTRO",
269 "INCOMPATIBLE_LICENSE"]
270 post_vars = ["BB_NUMBER_THREADS", "PARALLEL_MAKE", "PACKAGE_CLASSES",
271 "IMAGE_FSTYPES", "HOB_BUILD_TOOLCHAIN",
272 "HOB_BUILD_TOOLCHAIN_HEADERS"]
273 pre_values = {}
274 post_values = {}
275 changed_values = {}
276 pre_lines = None
277 post_lines = None
278
279 for var in self.config:
280 val = self.config[var]
281 if self.orig_config.get(var, None) != val:
282 changed_values[var] = val
283
284 if not len(changed_values):
285 return
286
287 for var in changed_values:
288 if var in pre_vars:
289 pre_values[var] = changed_values[var]
290 elif var in post_vars:
291 post_values[var] = changed_values[var]
292
293 with open(self.preconf, 'r') as pre:
294 pre_lines = pre.readlines()
295 pre_lines = self.updateConf(pre_lines, pre_values)
296 if len(pre_lines):
297 self.writeConfFile(self.preconf, pre_lines)
298
299 with open(self.postconf, 'r') as post:
300 post_lines = post.readlines()
301 post_lines = self.updateConf(post_lines, post_values)
302 if len(post_lines):
303 self.writeConfFile(self.postconf, post_lines)
304
305 del self.orig_config
306 self.orig_config = copy.deepcopy(self.config)
307
308 def insertTempBBPath(self, bbpath, bbfiles):
309 # read the original conf into a list
310 with open(self.postconf, 'r') as config:
311 config_lines = config.readlines()
312
313 if bbpath:
314 config_lines.append("BBPATH := \"${BBPATH}:%s\"\n" % bbpath)
315 if bbfiles:
316 config_lines.append("BBFILES := \"${BBFILES} %s\"\n" % bbfiles)
317
318 self.writeConfFile(self.postconf, config_lines)
319
320 def writeLayerConf(self):
321 # If we've not added/removed new layers don't write
322 if not self._isLayerConfDirty():
323 return
324
325 # This pattern should find the existing BBLAYERS
326 pattern = 'BBLAYERS\s=\s\".*\"'
327
328 replacement = self._constructLayerEntry()
329
330 with open(self.bblayers, "r") as f:
331 contents = f.read()
332 p = re.compile(pattern, re.DOTALL)
333 new = p.sub(replacement, contents)
334
335 self.writeConfFile(self.bblayers, new)
336
337 # set loaded_layers for dirtiness tracking
338 self.loaded_layers = copy.deepcopy(self.enabled_layers)
339
340 self.emit("layers-changed")
341
342 def configFound(self, handler, path):
343 self._addConfigFile(path)
344
345 def loadConfig(self, path):
346 self._addConfigFile(path)