| 1 |
import os
|
| 2 |
|
| 3 |
from debian_linux.config import ConfigCoreHierarchy
|
| 4 |
|
| 5 |
from kconfigeditor.kconfig.menu.file import FileChoice, FileConfig
|
| 6 |
|
| 7 |
class Files(dict):
|
| 8 |
def __init__(self, root):
|
| 9 |
self.kernelarch = {}
|
| 10 |
self.files = {}
|
| 11 |
self.filenames = {}
|
| 12 |
self.root = os.path.join(root, "debian/config")
|
| 13 |
self.config = ConfigCoreHierarchy([self.root])
|
| 14 |
|
| 15 |
self._read_base()
|
| 16 |
|
| 17 |
for key, files in self.filenames.iteritems():
|
| 18 |
r = self.setdefault(key, FileList())
|
| 19 |
for f in files:
|
| 20 |
if f in self.files:
|
| 21 |
f = self.files[f]
|
| 22 |
else:
|
| 23 |
f = self.files.setdefault(f, File(file(os.path.join(self.root, f)), f))
|
| 24 |
r.append_file(f)
|
| 25 |
|
| 26 |
def _read_arch(self, arch):
|
| 27 |
config_entry = self.config.merge('base', arch)
|
| 28 |
self.kernelarch[arch,] = config_entry.get('kernel-arch', arch)
|
| 29 |
|
| 30 |
kconfig = self.check_config("%s/config" % arch, True, arch)
|
| 31 |
self.filenames[arch,] = kconfig
|
| 32 |
|
| 33 |
for featureset in self.config['base', arch]['featuresets']:
|
| 34 |
self._read_featureset(arch, featureset)
|
| 35 |
|
| 36 |
def _read_base(self):
|
| 37 |
self.kernelarch[()] = None
|
| 38 |
self.filenames[()] = self.check_config('config', True)
|
| 39 |
|
| 40 |
for arch in self.config['base',]['arches']:
|
| 41 |
self._read_arch(arch)
|
| 42 |
|
| 43 |
def _read_featureset(self, arch, featureset):
|
| 44 |
# TODO
|
| 45 |
if featureset != 'none':
|
| 46 |
return
|
| 47 |
|
| 48 |
config_entry = self.config.merge('base', arch, featureset)
|
| 49 |
self.kernelarch[arch, featureset] = config_entry.get('kernel-arch', arch)
|
| 50 |
|
| 51 |
kconfig = []
|
| 52 |
kconfig.extend(self.check_config("featureset-%s/config" % featureset, False, None, featureset))
|
| 53 |
kconfig.extend(self.check_config("%s/%s/config" % (arch, featureset), False, arch, featureset))
|
| 54 |
self.filenames[arch, featureset] = kconfig
|
| 55 |
|
| 56 |
for flavour in self.config['base', arch, featureset]['flavours']:
|
| 57 |
self._read_flavour(arch, featureset, flavour)
|
| 58 |
|
| 59 |
def _read_flavour(self, arch, featureset, flavour):
|
| 60 |
config_entry = self.config.merge('base', arch, featureset, flavour)
|
| 61 |
self.kernelarch[arch, featureset, flavour] = config_entry.get('kernel-arch', arch)
|
| 62 |
|
| 63 |
kconfig = []
|
| 64 |
kconfig.extend(self.check_config("%s/config.%s" % (arch, flavour), False, arch, None, flavour))
|
| 65 |
kconfig.extend(self.check_config("%s/%s/config.%s" % (arch, featureset, flavour), False, arch, featureset, flavour))
|
| 66 |
self.filenames[arch, featureset, flavour] = kconfig
|
| 67 |
|
| 68 |
def _get_config(self, *entry_name):
|
| 69 |
entry_real = ('image',) + entry_name
|
| 70 |
entry = self.config.get(entry_real, None)
|
| 71 |
if entry is None:
|
| 72 |
return None
|
| 73 |
return entry.get('configs', None)
|
| 74 |
|
| 75 |
def check_config_default(self, fail, f):
|
| 76 |
f1 = self.root + '/' + f
|
| 77 |
if os.path.exists(f1):
|
| 78 |
return [f]
|
| 79 |
if fail:
|
| 80 |
raise RuntimeError("%s unavailable" % f)
|
| 81 |
return []
|
| 82 |
|
| 83 |
def check_config_files(self, files):
|
| 84 |
ret = []
|
| 85 |
for f in files:
|
| 86 |
f1 = self.root + '/' + f
|
| 87 |
if os.path.exists(f1):
|
| 88 |
ret.append(f)
|
| 89 |
break
|
| 90 |
else:
|
| 91 |
raise RuntimeError("%s unavailable" % f)
|
| 92 |
return ret
|
| 93 |
|
| 94 |
def check_config(self, default, fail, *entry_name):
|
| 95 |
configs = self._get_config(*entry_name)
|
| 96 |
if configs is None:
|
| 97 |
return self.check_config_default(fail, default)
|
| 98 |
return self.check_config_files(configs)
|
| 99 |
|
| 100 |
class FileList(object):
|
| 101 |
def __init__(self):
|
| 102 |
self._files = []
|
| 103 |
|
| 104 |
def append_file(self, item):
|
| 105 |
self._files.append(item)
|
| 106 |
|
| 107 |
class File(dict):
|
| 108 |
def __init__(self, fd, filename):
|
| 109 |
self.filename = filename
|
| 110 |
|
| 111 |
self.read(fd)
|
| 112 |
|
| 113 |
def _dump_file_choice(self, processed, ignored, have_prompt, f):
|
| 114 |
ret = []
|
| 115 |
for i in f:
|
| 116 |
if isinstance(i, FileConfig):
|
| 117 |
ret.extend(self._dump_file_config(processed, ignored, have_prompt, i))
|
| 118 |
if ret:
|
| 119 |
ret.insert(0, "## choice: %s" % f.prompt)
|
| 120 |
ret.append('## end choice')
|
| 121 |
return ret
|
| 122 |
|
| 123 |
def _dump_file_config(self, processed, ignored, have_prompt, i):
|
| 124 |
e = self.get(i.name, None)
|
| 125 |
if e is None:
|
| 126 |
return []
|
| 127 |
|
| 128 |
if i.name in processed:
|
| 129 |
return []
|
| 130 |
if not i.prompt:
|
| 131 |
if i.name in have_prompt:
|
| 132 |
return []
|
| 133 |
if ignored is not None:
|
| 134 |
ignored.add(i.name)
|
| 135 |
return []
|
| 136 |
processed.add(i.name)
|
| 137 |
return [e]
|
| 138 |
|
| 139 |
def _dump_file(self, processed, ignored, have_prompt, f):
|
| 140 |
ret = []
|
| 141 |
for i in f:
|
| 142 |
if isinstance(i, FileConfig):
|
| 143 |
ret.extend(self._dump_file_config(processed, ignored, have_prompt, i))
|
| 144 |
elif isinstance(i, FileChoice):
|
| 145 |
ret.extend(self._dump_file_choice(processed, ignored, have_prompt, i))
|
| 146 |
if ret:
|
| 147 |
ret[0:0] = ["##", "## file: %s" % f.filename, "##"]
|
| 148 |
ret.append('')
|
| 149 |
return ret
|
| 150 |
|
| 151 |
def _dump_prompt_file_config(self, have_prompt, i):
|
| 152 |
e = self.get(i.name, None)
|
| 153 |
if e is not None:
|
| 154 |
if i.prompt:
|
| 155 |
have_prompt.add(i.name)
|
| 156 |
|
| 157 |
def _dump_prompt_file(self, have_prompt, f):
|
| 158 |
for i in f:
|
| 159 |
if isinstance(i, FileConfig):
|
| 160 |
self._dump_prompt_file_config(have_prompt, i)
|
| 161 |
elif isinstance(i, FileChoice):
|
| 162 |
for i1 in i:
|
| 163 |
if isinstance(i1, FileConfig):
|
| 164 |
self._dump_prompt_file_config(have_prompt, i1)
|
| 165 |
|
| 166 |
def dump(self, root, menufiles, ignore_silent = False):
|
| 167 |
filename = os.path.join(root, self.filename)
|
| 168 |
if not os.path.exists(os.path.dirname(filename)):
|
| 169 |
os.makedirs(os.path.dirname(filename))
|
| 170 |
fd = file(filename, 'w')
|
| 171 |
|
| 172 |
def menufiles_cmp_key(entry):
|
| 173 |
filename_list = entry.filename.split('/')
|
| 174 |
if filename_list[-1] == 'Kconfig':
|
| 175 |
filename_list.pop()
|
| 176 |
else:
|
| 177 |
filename_list[-1] = filename_list[-1].replace('Kconfig.', '')
|
| 178 |
return filename_list
|
| 179 |
|
| 180 |
menufiles.sort(key = menufiles_cmp_key)
|
| 181 |
|
| 182 |
have_prompt = set()
|
| 183 |
for f in menufiles:
|
| 184 |
self._dump_prompt_file(have_prompt, f)
|
| 185 |
|
| 186 |
ret = []
|
| 187 |
processed = set()
|
| 188 |
ignored_sub = ignored = set()
|
| 189 |
if not ignore_silent:
|
| 190 |
ignored_sub = None
|
| 191 |
for f in menufiles:
|
| 192 |
ret.extend(self._dump_file(processed, ignored_sub, have_prompt, f))
|
| 193 |
|
| 194 |
s = set(self.keys())
|
| 195 |
unprocessed = s - processed - ignored
|
| 196 |
if unprocessed:
|
| 197 |
ret.extend(["##", "## file: unknown", "##"])
|
| 198 |
unprocessed = list(unprocessed)
|
| 199 |
unprocessed.sort()
|
| 200 |
for i in unprocessed:
|
| 201 |
e = self.get(i)
|
| 202 |
ret.append(e)
|
| 203 |
ret.append('')
|
| 204 |
|
| 205 |
for i in ret:
|
| 206 |
fd.write(str(i) + "\n")
|
| 207 |
|
| 208 |
def read(self, f):
|
| 209 |
for line in iter(f.readlines()):
|
| 210 |
line = line.strip()
|
| 211 |
if line.startswith("CONFIG_"):
|
| 212 |
i = line.find('=')
|
| 213 |
option = line[7:i]
|
| 214 |
value = line[i+1:]
|
| 215 |
if value in ('y', 'm'):
|
| 216 |
entry = FileEntryTristate(option, value)
|
| 217 |
else:
|
| 218 |
entry = FileEntryString(option, value)
|
| 219 |
self[option] = entry
|
| 220 |
elif line.startswith("# CONFIG_"):
|
| 221 |
option = line[9:-11]
|
| 222 |
self[option] = FileEntryTristate(option)
|
| 223 |
elif line.startswith("#") or not line:
|
| 224 |
pass
|
| 225 |
else:
|
| 226 |
raise RuntimeError, "Can't recognize %s" % line
|
| 227 |
|
| 228 |
# TODO
|
| 229 |
class FileEntryString(object):
|
| 230 |
__slots__ = "name", "value"
|
| 231 |
|
| 232 |
def __init__(self, name, value):
|
| 233 |
self.name = name
|
| 234 |
self.value = value
|
| 235 |
|
| 236 |
def __str__(self):
|
| 237 |
return "CONFIG_%s=%s" % (self.name, self.value)
|
| 238 |
|
| 239 |
# TODO
|
| 240 |
class FileEntryTristate(object):
|
| 241 |
__slots__ = "name", "value"
|
| 242 |
|
| 243 |
VALUE_NO = 0
|
| 244 |
VALUE_YES = 1
|
| 245 |
VALUE_MOD = 2
|
| 246 |
|
| 247 |
def __init__(self, name, value = None):
|
| 248 |
self.name = name
|
| 249 |
if value == 'n' or value is None:
|
| 250 |
self.value = self.VALUE_NO
|
| 251 |
elif value == 'y':
|
| 252 |
self.value = self.VALUE_YES
|
| 253 |
elif value == 'm':
|
| 254 |
self.value = self.VALUE_MOD
|
| 255 |
|
| 256 |
def __str__(self):
|
| 257 |
conf = "CONFIG_%s" % self.name
|
| 258 |
if self.value == self.VALUE_NO:
|
| 259 |
return "# %s is not set" % conf
|
| 260 |
elif self.value == self.VALUE_YES:
|
| 261 |
return "%s=y" % conf
|
| 262 |
elif self.value == self.VALUE_MOD:
|
| 263 |
return "%s=m" % conf
|
| 264 |
|