4 sys.path.append('debian/lib/python')
9 from debian_linux.abi import Symbols
10 from debian_linux.config import ConfigCoreDump
11 from debian_linux.debian import *
14 class CheckAbi(object):
15 class SymbolInfo(object):
16 def __init__(self, symbol, symbol_ref=None):
18 self.symbol_ref = symbol_ref or symbol
22 return self.symbol.module
26 return self.symbol.name
28 def write(self, out, ignored):
31 info.append("ignored")
32 for name in ('module', 'version', 'export'):
33 data = getattr(self.symbol, name)
34 data_ref = getattr(self.symbol_ref, name)
36 info.append("%s: %s -> %s" % (name, data_ref, data))
38 info.append("%s: %s" % (name, data))
39 out.write("%-48s %s\n" % (self.symbol.name, ", ".join(info)))
41 def __init__(self, config, dir, arch, featureset, flavour):
43 self.arch, self.featureset, self.flavour = arch, featureset, flavour
45 self.filename_new = "%s/Module.symvers" % dir
47 changelog = Changelog(version=VersionLinux)[0]
48 version = changelog.version.linux_version
49 abiname = self.config['abi',]['abiname']
50 self.filename_ref = "debian/abi/%s-%s/%s_%s_%s" % (version, abiname, arch, featureset, flavour)
52 def __call__(self, out):
55 new = Symbols(open(self.filename_new))
57 ref = Symbols(open(self.filename_ref))
59 out.write("Can't read ABI reference. ABI not checked! Continuing.\n")
62 symbols, add, change, remove = self._cmp(ref, new)
64 ignore = self._ignore(symbols)
66 add_effective = add - ignore
67 change_effective = change - ignore
68 remove_effective = remove - ignore
70 if change_effective or remove_effective:
71 out.write("ABI has changed! Refusing to continue.\n")
73 elif change or remove:
74 out.write("ABI has changed but all changes have been ignored. Continuing.\n")
76 out.write("New symbols have been added. Continuing.\n")
78 out.write("New symbols have been added but have been ignored. Continuing.\n")
80 out.write("No ABI changes.\n")
83 out.write("\nAdded symbols:\n")
84 for name in sorted(add):
85 symbols[name].write(out, name in ignore)
88 out.write("\nChanged symbols:\n")
89 for name in sorted(change):
90 symbols[name].write(out, name in ignore)
93 out.write("\nRemoved symbols:\n")
94 for name in sorted(remove):
95 symbols[name].write(out, name in ignore)
99 def _cmp(self, ref, new):
100 ref_names = set(ref.keys())
101 new_names = set(new.keys())
109 for name in new_names - ref_names:
111 symbols[name] = self.SymbolInfo(new[name])
113 for name in ref_names.intersection(new_names):
119 symbols[name] = self.SymbolInfo(s_new, s_ref)
121 for name in ref_names - new_names:
123 symbols[name] = self.SymbolInfo(ref[name])
125 return symbols, add, change, remove
127 def _ignore_pattern(self, pattern):
129 for i in re.split(r'(\*\*?)', pattern):
135 ret.append(re.escape(i))
136 return re.compile('^' + ''.join(ret) + '$')
138 def _ignore(self, symbols):
139 # TODO: let config merge this lists
141 configs.append(self.config.get(('abi', self.arch, self.featureset, self.flavour), {}))
142 configs.append(self.config.get(('abi', self.arch, None, self.flavour), {}))
143 configs.append(self.config.get(('abi', self.arch, self.featureset), {}))
144 configs.append(self.config.get(('abi', self.arch), {}))
145 configs.append(self.config.get(('abi', None, self.featureset), {}))
146 configs.append(self.config.get(('abi',), {}))
149 for config in configs:
150 ignores.update(config.get('ignore-changes', []))
153 for ignore in ignores:
156 type, ignore = ignore.split(':')
157 if type in ('name', 'module'):
158 p = self._ignore_pattern(ignore)
159 for symbol in symbols.itervalues():
160 if p.match(getattr(symbol, type)):
161 filtered.add(symbol.name)
163 raise NotImplementedError
168 class CheckImage(object):
169 def __init__(self, config, dir, arch, featureset, flavour):
171 self.arch, self.featureset, self.flavour = arch, featureset, flavour
173 self.config_entry_build = config.merge('build', arch, featureset, flavour)
174 self.config_entry_image = config.merge('image', arch, featureset, flavour)
176 def __call__(self, out):
177 image = self.config_entry_build.get('image-file')
183 image = os.path.join(self.dir, image)
187 fail |= self.check_size(out, image)
191 def check_size(self, out, image):
192 value = self.config_entry_image.get('check-size')
199 size = os.stat(image)[stat.ST_SIZE]
202 out.write('Image too large (%d > %d)! Refusing to continue.\n' % (size, value))
205 out.write('Image fits (%d <= %d). Continuing.\n' % (size, value))
210 def __init__(self, dir, arch, featureset, flavour):
211 self.args = dir, arch, featureset, flavour
213 self.config = ConfigCoreDump(fp=file("debian/config.defines.dump"))
218 for c in CheckAbi, CheckImage:
219 fail |= c(self.config, *self.args)(sys.stdout)
224 if __name__ == '__main__':
225 sys.exit(Main(*sys.argv[1:])())