diff options
Diffstat (limited to 'debian/bin')
-rw-r--r-- | debian/bin/abiupdate.py | 184 | ||||
-rw-r--r-- | debian/bin/buildcheck.py | 225 | ||||
-rw-r--r-- | debian/bin/check-patches.sh | 13 | ||||
-rwxr-xr-x | debian/bin/gencontrol.py | 358 | ||||
-rw-r--r-- | debian/bin/genorig.py | 136 | ||||
-rw-r--r-- | debian/bin/kconfig.py | 37 | ||||
-rw-r--r-- | debian/bin/patch.apply | 227 | ||||
-rw-r--r-- | debian/bin/perf | 11 | ||||
-rw-r--r-- | debian/bin/test-patches | 81 |
9 files changed, 1272 insertions, 0 deletions
diff --git a/debian/bin/abiupdate.py b/debian/bin/abiupdate.py new file mode 100644 index 00000000..c0b21b5a --- /dev/null +++ b/debian/bin/abiupdate.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python + +import sys +sys.path.append(sys.path[0] + "/../lib/python") + +import optparse, os, shutil, tempfile, urllib2 +from debian_linux.abi import Symbols +from debian_linux.config import * +from debian_linux.debian import * + +default_url_base = "http://ftp.de.debian.org/debian/" +default_url_base_incoming = "http://incoming.debian.org/" + +class url_debian_flat(object): + def __init__(self, base): + self.base = base + + def __call__(self, source, filename): + return self.base + filename + +class url_debian_pool(object): + def __init__(self, base): + self.base = base + + def __call__(self, source, filename): + return self.base + "pool/main/" + source[0] + "/" + source + "/" + filename + +class main(object): + dir = None + + def __init__(self, url, url_config = None, arch = None, featureset = None, flavour = None): + self.log = sys.stdout.write + + self.url = self.url_config = url + if url_config is not None: + self.url_config = url_config + self.override_arch = arch + self.override_featureset = featureset + self.override_flavour = flavour + + changelog = Changelog(version = VersionLinux) + while changelog[0].distribution == 'UNRELEASED': + changelog.pop(0) + changelog = changelog[0] + + self.source = changelog.source + self.version = changelog.version.linux_version + self.version_source = changelog.version.complete + + local_config = ConfigCoreDump(fp = file("debian/config.defines.dump")) + + self.version_abi = self.version + '-' + local_config['abi',]['abiname'] + + def __call__(self): + self.dir = tempfile.mkdtemp(prefix = 'abiupdate') + try: + self.log("Retreive config\n") + config = self.get_config() + if self.override_arch: + arches = [self.override_arch] + else: + arches = config[('base',)]['arches'] + for arch in arches: + self.update_arch(config, arch) + finally: + shutil.rmtree(self.dir) + + def extract_package(self, filename, base): + base_out = self.dir + "/" + base + os.mkdir(base_out) + os.system("dpkg-deb --extract %s %s" % (filename, base_out)) + return base_out + + def get_abi(self, arch, prefix): + filename = "linux-headers-%s-%s_%s_%s.deb" % (self.version_abi, prefix, self.version_source, arch) + f = self.retrieve_package(self.url, filename) + d = self.extract_package(f, "linux-headers-%s_%s" % (prefix, arch)) + f1 = d + "/usr/src/linux-headers-%s-%s/Module.symvers" % (self.version_abi, prefix) + s = Symbols(open(f1)) + shutil.rmtree(d) + return s + + def get_config(self): + filename = "linux-support-%s_%s_all.deb" % (self.version_abi, self.version_source) + f = self.retrieve_package(self.url_config, filename) + d = self.extract_package(f, "linux-support") + c = d + "/usr/src/linux-support-" + self.version_abi + "/config.defines.dump" + config = ConfigCoreDump(fp = file(c)) + shutil.rmtree(d) + return config + + def retrieve_package(self, url, filename): + u = url(self.source, filename) + filename_out = self.dir + "/" + filename + + f_in = urllib2.urlopen(u) + f_out = file(filename_out, 'w') + while 1: + r = f_in.read() + if not r: + break + f_out.write(r) + return filename_out + + def save_abi(self, symbols, arch, featureset, flavour): + dir = "debian/abi/%s" % self.version_abi + if not os.path.exists(dir): + os.makedirs(dir) + out = "%s/%s_%s_%s" % (dir, arch, featureset, flavour) + symbols.write(open(out, 'w')) + + def update_arch(self, config, arch): + if self.override_featureset: + featuresets = [self.override_featureset] + else: + featuresets = config[('base', arch)]['featuresets'] + for featureset in featuresets: + self.update_featureset(config, arch, featureset) + + def update_featureset(self, config, arch, featureset): + config_base = config.merge('base', arch, featureset) + + if not config_base.get('enabled', True): + return + + if self.override_flavour: + flavours = [self.override_flavour] + else: + flavours = config_base['flavours'] + for flavour in flavours: + self.update_flavour(config, arch, featureset, flavour) + + def update_flavour(self, config, arch, featureset, flavour): + config_base = config.merge('base', arch, featureset, flavour) + + if not config_base.get('modules', True): + return + + self.log("Updating ABI for arch %s, featureset %s, flavour %s: " % (arch, featureset, flavour)) + try: + if featureset == 'none': + localversion = flavour + else: + localversion = featureset + '-' + flavour + + abi = self.get_abi(arch, localversion) + self.save_abi(abi, arch, featureset, flavour) + self.log("Ok.\n") + except urllib2.HTTPError, e: + self.log("Failed to retrieve %s: %s\n" % (e.filename, e)) + except StandardError, e: + self.log("FAILED!\n") + import traceback + traceback.print_exc(None, sys.stdout) + +if __name__ == '__main__': + options = optparse.OptionParser() + options.add_option("-i", "--incoming", action = "store_true", dest = "incoming") + options.add_option("--incoming-config", action = "store_true", dest = "incoming_config") + options.add_option("-u", "--url-base", dest = "url_base", default = default_url_base) + options.add_option("--url-base-incoming", dest = "url_base_incoming", default = default_url_base_incoming) + + opts, args = options.parse_args() + + kw = {} + if len(args) >= 1: + kw['arch'] =args[0] + if len(args) >= 2: + kw['featureset'] =args[1] + if len(args) >= 3: + kw['flavour'] =args[2] + + url_base = url_debian_pool(opts.url_base) + url_base_incoming = url_debian_flat(opts.url_base_incoming) + if opts.incoming_config: + url = url_config = url_base_incoming + else: + url_config = url_base + if opts.incoming: + url = url_base_incoming + else: + url = url_base + + main(url, url_config, **kw)() diff --git a/debian/bin/buildcheck.py b/debian/bin/buildcheck.py new file mode 100644 index 00000000..3297ba24 --- /dev/null +++ b/debian/bin/buildcheck.py @@ -0,0 +1,225 @@ +#!/usr/bin/python + +import sys +sys.path.append('debian/lib/python') + +import fnmatch +import stat + +from debian_linux.abi import Symbols +from debian_linux.config import ConfigCoreDump +from debian_linux.debian import * + + +class CheckAbi(object): + class SymbolInfo(object): + def __init__(self, symbol, symbol_ref=None): + self.symbol = symbol + self.symbol_ref = symbol_ref or symbol + + @property + def module(self): + return self.symbol.module + + @property + def name(self): + return self.symbol.name + + def write(self, out, ignored): + info = [] + if ignored: + info.append("ignored") + for name in ('module', 'version', 'export'): + data = getattr(self.symbol, name) + data_ref = getattr(self.symbol_ref, name) + if data != data_ref: + info.append("%s: %s -> %s" % (name, data_ref, data)) + else: + info.append("%s: %s" % (name, data)) + out.write("%-48s %s\n" % (self.symbol.name, ", ".join(info))) + + def __init__(self, config, dir, arch, featureset, flavour): + self.config = config + self.arch, self.featureset, self.flavour = arch, featureset, flavour + + self.filename_new = "%s/Module.symvers" % dir + + changelog = Changelog(version=VersionLinux)[0] + version = changelog.version.linux_version + abiname = self.config['abi',]['abiname'] + self.filename_ref = "debian/abi/%s-%s/%s_%s_%s" % (version, abiname, arch, featureset, flavour) + + def __call__(self, out): + ret = 0 + + new = Symbols(open(self.filename_new)) + try: + ref = Symbols(open(self.filename_ref)) + except IOError: + out.write("Can't read ABI reference. ABI not checked! Continuing.\n") + return 0 + + symbols, add, change, remove = self._cmp(ref, new) + + ignore = self._ignore(symbols) + + add_effective = add - ignore + change_effective = change - ignore + remove_effective = remove - ignore + + if change_effective or remove_effective: + out.write("ABI has changed! Refusing to continue.\n") + ret = 1 + elif change or remove: + out.write("ABI has changed but all changes have been ignored. Continuing.\n") + elif add_effective: + out.write("New symbols have been added. Continuing.\n") + elif add: + out.write("New symbols have been added but have been ignored. Continuing.\n") + else: + out.write("No ABI changes.\n") + + if add: + out.write("\nAdded symbols:\n") + for name in sorted(add): + symbols[name].write(out, name in ignore) + + if change: + out.write("\nChanged symbols:\n") + for name in sorted(change): + symbols[name].write(out, name in ignore) + + if remove: + out.write("\nRemoved symbols:\n") + for name in sorted(remove): + symbols[name].write(out, name in ignore) + + return ret + + def _cmp(self, ref, new): + ref_names = set(ref.keys()) + new_names = set(new.keys()) + + add = set() + change = set() + remove = set() + + symbols = {} + + for name in new_names - ref_names: + add.add(name) + symbols[name] = self.SymbolInfo(new[name]) + + for name in ref_names.intersection(new_names): + s_ref = ref[name] + s_new = new[name] + + if s_ref != s_new: + change.add(name) + symbols[name] = self.SymbolInfo(s_new, s_ref) + + for name in ref_names - new_names: + remove.add(name) + symbols[name] = self.SymbolInfo(ref[name]) + + return symbols, add, change, remove + + def _ignore_pattern(self, pattern): + ret = [] + for i in re.split(r'(\*\*?)', pattern): + if i == '*': + ret.append(r'[^!]+') + elif i == '**': + ret.append(r'.+') + elif i: + ret.append(re.escape(i)) + return re.compile('^' + ''.join(ret) + '$') + + def _ignore(self, symbols): + # TODO: let config merge this lists + configs = [] + configs.append(self.config.get(('abi', self.arch, self.featureset, self.flavour), {})) + configs.append(self.config.get(('abi', self.arch, None, self.flavour), {})) + configs.append(self.config.get(('abi', self.arch, self.featureset), {})) + configs.append(self.config.get(('abi', self.arch), {})) + configs.append(self.config.get(('abi', None, self.featureset), {})) + configs.append(self.config.get(('abi',), {})) + + ignores = set() + for config in configs: + ignores.update(config.get('ignore-changes', [])) + + filtered = set() + for ignore in ignores: + type = 'name' + if ':' in ignore: + type, ignore = ignore.split(':') + if type in ('name', 'module'): + p = self._ignore_pattern(ignore) + for symbol in symbols.itervalues(): + if p.match(getattr(symbol, type)): + filtered.add(symbol.name) + else: + raise NotImplementedError + + return filtered + + +class CheckImage(object): + def __init__(self, config, dir, arch, featureset, flavour): + self.dir = dir + self.arch, self.featureset, self.flavour = arch, featureset, flavour + + self.config_entry_build = config.merge('build', arch, featureset, flavour) + self.config_entry_image = config.merge('image', arch, featureset, flavour) + + def __call__(self, out): + image = self.config_entry_build.get('image-file') + + if not image: + # TODO: Bail out + return 0 + + image = os.path.join(self.dir, image) + + fail = 0 + + fail |= self.check_size(out, image) + + return fail + + def check_size(self, out, image): + value = self.config_entry_image.get('check-size') + + if not value: + return 0 + + value = int(value) + + size = os.stat(image)[stat.ST_SIZE] + + if size > value: + out.write('Image too large (%d > %d)! Refusing to continue.\n' % (size, value)) + return 1 + + out.write('Image fits (%d <= %d). Continuing.\n' % (size, value)) + return 0 + + +class Main(object): + def __init__(self, dir, arch, featureset, flavour): + self.args = dir, arch, featureset, flavour + + self.config = ConfigCoreDump(fp=file("debian/config.defines.dump")) + + def __call__(self): + fail = 0 + + for c in CheckAbi, CheckImage: + fail |= c(self.config, *self.args)(sys.stdout) + + return fail + + +if __name__ == '__main__': + sys.exit(Main(*sys.argv[1:])()) diff --git a/debian/bin/check-patches.sh b/debian/bin/check-patches.sh new file mode 100644 index 00000000..3a733fae --- /dev/null +++ b/debian/bin/check-patches.sh @@ -0,0 +1,13 @@ +#!/bin/sh -e + +TMPDIR=$(mktemp -d) +trap "rm -rf $TMPDIR" EXIT +grep -v "^#" debian/patches/series/* | awk '{if (NF >= 2) print "debian/patches/" $2}' | sort -u > $TMPDIR/used +find debian/patches ! -path '*/series*' -type f -name "*.diff" -o -name "*.patch" -printf "%p\n" | sort > $TMPDIR/avail +echo "Used patches" +echo "==============" +cat $TMPDIR/used +echo +echo "Unused patches" +echo "==============" +fgrep -v -f $TMPDIR/used $TMPDIR/avail diff --git a/debian/bin/gencontrol.py b/debian/bin/gencontrol.py new file mode 100755 index 00000000..bcf0215e --- /dev/null +++ b/debian/bin/gencontrol.py @@ -0,0 +1,358 @@ +#!/usr/bin/env python + +import os, sys +sys.path.append("debian/lib/python") + +from debian_linux.config import ConfigCoreHierarchy +from debian_linux.debian import * +from debian_linux.gencontrol import Gencontrol as Base +from debian_linux.utils import Templates + +class Gencontrol(Base): + def __init__(self, config_dirs = ["debian/config"], template_dirs = ["debian/templates"]): + super(Gencontrol, self).__init__(ConfigCoreHierarchy(config_dirs), Templates(template_dirs), VersionLinux) + self.process_changelog() + self.config_dirs = config_dirs + + def _setup_makeflags(self, names, makeflags, data): + for src, dst, optional in names: + if src in data or not optional: + makeflags[dst] = data[src] + + def do_main_setup(self, vars, makeflags, extra): + super(Gencontrol, self).do_main_setup(vars, makeflags, extra) + makeflags.update({ + 'MAJOR': self.version.linux_major, + 'VERSION': self.version.linux_version, + 'UPSTREAMVERSION': self.version.linux_upstream, + 'ABINAME': self.abiname, + 'SOURCEVERSION': self.version.complete, + }) + + def do_main_packages(self, packages, vars, makeflags, extra): + packages.extend(self.process_packages(self.templates["control.main"], self.vars)) + + arch_makeflags = ( + ('kernel-arch', 'KERNEL_ARCH', False), + ) + + def do_arch_setup(self, vars, makeflags, arch, extra): + config_base = self.config.merge('base', arch) + self._setup_makeflags(self.arch_makeflags, makeflags, config_base) + + def do_arch_packages(self, packages, makefile, arch, vars, makeflags, extra): + headers_arch = self.templates["control.headers.arch"] + packages_headers_arch = self.process_packages(headers_arch, vars) + + libc_dev = self.templates["control.libc-dev"] + packages_headers_arch[0:0] = self.process_packages(libc_dev, {}) + + packages_headers_arch[-1]['Depends'].extend(PackageRelation()) + extra['headers_arch_depends'] = packages_headers_arch[-1]['Depends'] + + self.merge_packages(packages, packages_headers_arch, arch) + + cmds_binary_arch = ["$(MAKE) -f debian/rules.real binary-arch-arch %s" % makeflags] + cmds_source = ["$(MAKE) -f debian/rules.real source-arch %s" % makeflags] + makefile.add('binary-arch_%s_real' % arch, cmds = cmds_binary_arch) + makefile.add('source_%s_real' % arch, cmds = cmds_source) + + def do_featureset_setup(self, vars, makeflags, arch, featureset, extra): + config_base = self.config.merge('base', arch, featureset) + makeflags['LOCALVERSION_HEADERS'] = vars['localversion_headers'] = vars['localversion'] + + def do_featureset_packages(self, packages, makefile, arch, featureset, vars, makeflags, extra): + headers_featureset = self.templates["control.headers.featureset"] + package_headers = self.process_package(headers_featureset[0], vars) + + self.merge_packages(packages, (package_headers,), arch) + + cmds_binary_arch = ["$(MAKE) -f debian/rules.real binary-arch-featureset %s" % makeflags] + cmds_source = ["$(MAKE) -f debian/rules.real source-featureset %s" % makeflags] + makefile.add('binary-arch_%s_%s_real' % (arch, featureset), cmds = cmds_binary_arch) + makefile.add('source_%s_%s_real' % (arch, featureset), cmds = cmds_source) + + flavour_makeflags_base = ( + ('compiler', 'COMPILER', False), + ('kernel-arch', 'KERNEL_ARCH', False), + ('cflags', 'CFLAGS_KERNEL', True), + ('override-host-type', 'OVERRIDE_HOST_TYPE', True), + ) + + flavour_makeflags_image = ( + ('type', 'TYPE', False), + ('initramfs', 'INITRAMFS', True), + ) + + flavour_makeflags_other = ( + ('localversion', 'LOCALVERSION', False), + ('localversion-image', 'LOCALVERSION_IMAGE', True), + ) + + def do_flavour_setup(self, vars, makeflags, arch, featureset, flavour, extra): + config_base = self.config.merge('base', arch, featureset, flavour) + config_description = self.config.merge('description', arch, featureset, flavour) + config_image = self.config.merge('image', arch, featureset, flavour) + + vars['class'] = config_description['hardware'] + vars['longclass'] = config_description.get('hardware-long') or vars['class'] + + vars['localversion-image'] = vars['localversion'] + override_localversion = config_image.get('override-localversion', None) + if override_localversion is not None: + vars['localversion-image'] = vars['localversion_headers'] + '-' + override_localversion + + self._setup_makeflags(self.flavour_makeflags_base, makeflags, config_base) + self._setup_makeflags(self.flavour_makeflags_image, makeflags, config_image) + self._setup_makeflags(self.flavour_makeflags_other, makeflags, vars) + + def do_flavour_packages(self, packages, makefile, arch, featureset, flavour, vars, makeflags, extra): + headers = self.templates["control.headers"] + + config_entry_base = self.config.merge('base', arch, featureset, flavour) + config_entry_description = self.config.merge('description', arch, featureset, flavour) + config_entry_image = self.config.merge('image', arch, featureset, flavour) + config_entry_image_dbg = self.config.merge('image-dbg', arch, featureset, flavour) + config_entry_relations = self.config.merge('relations', arch, featureset, flavour) + + compiler = config_entry_base.get('compiler', 'gcc') + relations_compiler = PackageRelation(config_entry_relations[compiler]) + relations_compiler_build_dep = PackageRelation(config_entry_relations[compiler]) + for group in relations_compiler_build_dep: + for item in group: + item.arches = [arch] + packages['source']['Build-Depends'].extend(relations_compiler_build_dep) + + image_fields = {'Description': PackageDescription()} + for field in 'Depends', 'Provides', 'Suggests', 'Recommends', 'Conflicts': + image_fields[field] = PackageRelation(config_entry_image.get(field.lower(), None), override_arches=(arch,)) + + if config_entry_image.get('initramfs', True): + generators = config_entry_image['initramfs-generators'] + config_entry_commands_initramfs = self.config.merge('commands-image-initramfs-generators', arch, featureset, flavour) + commands = [config_entry_commands_initramfs[i] for i in generators if config_entry_commands_initramfs.has_key(i)] + makeflags['INITRD_CMD'] = ' '.join(commands) + l_depends = PackageRelationGroup() + for i in generators: + i = config_entry_relations.get(i, i) + l_depends.append(i) + a = PackageRelationEntry(i) + if a.operator is not None: + a.operator = -a.operator + image_fields['Conflicts'].append(PackageRelationGroup([a])) + image_fields['Depends'].append(l_depends) + + desc_parts = self.config.get_merge('description', arch, featureset, flavour, 'parts') + if desc_parts: + # XXX: Workaround, we need to support multiple entries of the same name + parts = list(set(desc_parts)) + parts.sort() + desc = image_fields['Description'] + for part in parts: + desc.append(config_entry_description['part-long-' + part]) + desc.append_short(config_entry_description.get('part-short-' + part, '')) + + packages_dummy = [] + packages_own = [] + + if config_entry_image['type'] == 'plain-s390-tape': + image = self.templates["control.image.type-standalone"] + build_modules = False + elif config_entry_image['type'] == 'plain-xen': + raise RuntimeError + image = self.templates["control.image.type-modulesextra"] + build_modules = True + config_entry_xen = self.config.merge('xen', arch, featureset, flavour) + if config_entry_xen.get('dom0-support', True): + p = self.process_packages(self.templates['control.xen-linux-system'], vars) + l = PackageRelationGroup() + xen_versions = [] + for xen_flavour in config_entry_xen['flavours']: + for version in config_entry_xen['versions']: + l.append("xen-hypervisor-%s-%s" % (version, xen_flavour)) + xen_versions.append('%s-%s' % (version, xen_flavour)) + makeflags['XEN_VERSIONS'] = ' '.join(xen_versions) + p[0]['Depends'].append(l) + packages_dummy.extend(p) + else: + build_modules = True + image = self.templates["control.image.type-%s" % config_entry_image['type']] + #image = self.templates["control.image.type-modulesinline"] + + config_entry_xen = self.config.merge('xen', arch, featureset, flavour) + if config_entry_xen.get('dom0-support', False): + p = self.process_packages(self.templates['control.xen-linux-system'], vars) + l = PackageRelationGroup() + for xen_flavour in config_entry_xen['flavours']: + l.append("xen-hypervisor-%s" % xen_flavour) + p[0]['Depends'].append(l) + packages_dummy.extend(p) + + vars.setdefault('desc', None) + + packages_own.append(self.process_real_image(image[0], image_fields, vars)) + packages_own.extend(self.process_packages(image[1:], vars)) + + if build_modules: + makeflags['MODULES'] = True + package_headers = self.process_package(headers[0], vars) + package_headers['Depends'].extend(relations_compiler) + packages_own.append(package_headers) + extra['headers_arch_depends'].append('%s (= ${binary:Version})' % packages_own[-1]['Package']) + + build_debug = config_entry_image_dbg.get('enabled') + if build_debug: + makeflags['DEBUG'] = True + packages_own.extend(self.process_packages(self.templates['control.image-dbg'], vars)) + + self.merge_packages(packages, packages_own + packages_dummy, arch) + + if config_entry_image['type'] == 'plain-xen': + for i in ('postinst', 'postrm', 'prerm'): + j = self.substitute(self.templates["image.xen.%s" % i], vars) + file("debian/%s.%s" % (packages_own[0]['Package'], i), 'w').write(j) + + def get_config(*entry_name): + entry_real = ('image',) + entry_name + entry = self.config.get(entry_real, None) + if entry is None: + return None + return entry.get('configs', None) + + def check_config_default(fail, f): + for d in self.config_dirs[::-1]: + f1 = d + '/' + f + if os.path.exists(f1): + return [f1] + if fail: + raise RuntimeError("%s unavailable" % f) + return [] + + def check_config_files(files): + ret = [] + for f in files: + for d in self.config_dirs[::-1]: + f1 = d + '/' + f + if os.path.exists(f1): + ret.append(f1) + break + else: + raise RuntimeError("%s unavailable" % f) + return ret + + def check_config(default, fail, *entry_name): + configs = get_config(*entry_name) + if configs is None: + return check_config_default(fail, default) + return check_config_files(configs) + + kconfig = check_config('config', True) + kconfig.extend(check_config("%s/config" % arch, True, arch)) + kconfig.extend(check_config("%s/config.%s" % (arch, flavour), False, arch, None, flavour)) + kconfig.extend(check_config("featureset-%s/config" % featureset, False, None, featureset)) + kconfig.extend(check_config("%s/%s/config" % (arch, featureset), False, arch, featureset)) + kconfig.extend(check_config("%s/%s/config.%s" % (arch, featureset, flavour), False, arch, featureset, flavour)) + makeflags['KCONFIG'] = ' '.join(kconfig) + if build_debug: + makeflags['KCONFIG_OPTIONS'] = '-o DEBUG_INFO=y' + + cmds_binary_arch = ["$(MAKE) -f debian/rules.real binary-arch-flavour %s" % makeflags] + if packages_dummy: + cmds_binary_arch.append("$(MAKE) -f debian/rules.real install-dummy DH_OPTIONS='%s' %s" % (' '.join(["-p%s" % i['Package'] for i in packages_dummy]), makeflags)) + cmds_build = ["$(MAKE) -f debian/rules.real build %s" % makeflags] + cmds_setup = ["$(MAKE) -f debian/rules.real setup-flavour %s" % makeflags] + makefile.add('binary-arch_%s_%s_%s_real' % (arch, featureset, flavour), cmds = cmds_binary_arch) + makefile.add('build_%s_%s_%s_real' % (arch, featureset, flavour), cmds = cmds_build) + makefile.add('setup_%s_%s_%s_real' % (arch, featureset, flavour), cmds = cmds_setup) + + def do_extra(self, packages, makefile): + apply = self.templates['patch.apply'] + + vars = { + 'revisions': 'orig base ' + ' '.join([i.revision for i in self.versions[::-1]]), + 'upstream': self.version.upstream, + 'linux_upstream': self.version.linux_upstream, + 'abiname': self.abiname, + } + + apply = self.substitute(apply, vars) + + file('debian/bin/patch.apply', 'w').write(apply) + + def merge_packages(self, packages, new, arch): + for new_package in new: + name = new_package['Package'] + if name in packages: + package = packages.get(name) + package['Architecture'].append(arch) + + for field in 'Depends', 'Provides', 'Suggests', 'Recommends', 'Conflicts': + if field in new_package: + if field in package: + v = package[field] + v.extend(new_package[field]) + else: + package[field] = new_package[field] + + else: + new_package['Architecture'] = [arch] + packages.append(new_package) + + def process_changelog(self): + act_upstream = self.changelog[0].version.linux_upstream + versions = [] + for i in self.changelog: + if i.version.linux_upstream != act_upstream: + break + versions.append(i.version) + self.versions = versions + version = self.version = self.changelog[0].version + if self.version.linux_modifier is not None: + self.abiname = '' + else: + self.abiname = '-%s' % self.config['abi',]['abiname'] + self.vars = { + 'upstreamversion': self.version.linux_upstream, + 'version': self.version.linux_version, + 'source_upstream': self.version.upstream, + 'major': self.version.linux_major, + 'abiname': self.abiname, + } + self.config['version',] = {'source': self.version.complete, 'abiname': self.abiname} + + distribution = self.changelog[0].distribution + +# Skip version/distribution checks for SLP + distribution = 'SLP' + + if distribution in ('unstable', ): + if (version.linux_revision_experimental or + version.linux_revision_other): + raise RuntimeError("Can't upload to %s with a version of %s" % + (distribution, version)) + if distribution in ('experimental', ): + if not version.linux_revision_experimental: + raise RuntimeError("Can't upload to %s with a version of %s" % + (distribution, version)) + + def process_real_image(self, entry, fields, vars): + entry = self.process_package(entry, vars) + for key, value in fields.iteritems(): + if key in entry: + real = entry[key] + real.extend(value) + elif value: + entry[key] = value + return entry + + def write(self, packages, makefile): + self.write_config() + super(Gencontrol, self).write(packages, makefile) + + def write_config(self): + f = file("debian/config.defines.dump", 'w') + self.config.dump(f) + f.close() + +if __name__ == '__main__': + Gencontrol()() diff --git a/debian/bin/genorig.py b/debian/bin/genorig.py new file mode 100644 index 00000000..8a0979d1 --- /dev/null +++ b/debian/bin/genorig.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python + +import sys +sys.path.append("debian/lib/python") + +import os +import os.path +import re +import shutil +import subprocess + +from debian_linux.debian import Changelog, VersionLinux +from debian_linux.patches import PatchSeries + +class Main(object): + def __init__(self, input_files, override_version): + self.log = sys.stdout.write + + self.input_files = input_files + + changelog = Changelog(version = VersionLinux)[0] + source = changelog.source + version = changelog.version + + if override_version: + version = VersionLinux('%s-undef' % override_version) + + self.version_dfsg = version.linux_dfsg + if self.version_dfsg is None: + self.version_dfsg = '0' + + self.log('Using source name %s, version %s, dfsg %s\n' % (source, version.upstream, self.version_dfsg)) + + self.orig = '%s-%s' % (source, version.upstream) + self.orig_tar = '%s_%s.orig.tar.gz' % (source, version.upstream) + self.tag = 'v' + version.upstream.replace('~', '-') + + def __call__(self): + import tempfile + self.dir = tempfile.mkdtemp(prefix = 'genorig', dir = 'debian') + try: + if os.path.isdir(self.input_files[0]): + self.upstream_export(self.input_files[0]) + else: + self.upstream_extract(self.input_files[0]) + if len(self.input_files) > 1: + self.upstream_patch(self.input_files[1]) + self.debian_patch() + self.tar() + finally: + shutil.rmtree(self.dir) + + def upstream_export(self, input_repo): + self.log("Exporting %s from %s\n" % (self.tag, input_repo)) + + archive_proc = subprocess.Popen(['git', 'archive', '--format=tar', + '--prefix=%s/' % self.orig, self.tag], + cwd=input_repo, + stdout=subprocess.PIPE) + extract_proc = subprocess.Popen(['tar', '-xf', '-'], cwd=self.dir, + stdin=archive_proc.stdout) + + if extract_proc.wait(): + raise RuntimeError("Can't extract tarball") + + def upstream_extract(self, input_tar): + self.log("Extracting tarball %s\n" % input_tar) + match = re.match(r'(^|.*/)(?P<dir>linux-\d+\.\d+\.\d+(-\S+)?)\.tar(\.(?P<extension>(bz2|gz)))?$', input_tar) + if not match: + raise RuntimeError("Can't identify name of tarball") + + cmdline = ['tar', '-xf', input_tar, '-C', self.dir] + if match.group('extension') == 'bz2': + cmdline.append('-j') + elif match.group('extension') == 'gz': + cmdline.append('-z') + + if subprocess.Popen(cmdline).wait(): + raise RuntimeError("Can't extract tarball") + + os.rename(os.path.join(self.dir, match.group('dir')), os.path.join(self.dir, self.orig)) + + def upstream_patch(self, input_patch): + self.log("Patching source with %s\n" % input_patch) + match = re.match(r'(^|.*/)patch-\d+\.\d+\.\d+(-\S+?)?(\.(?P<extension>(bz2|gz)))?$', input_patch) + if not match: + raise RuntimeError("Can't identify name of patch") + cmdline = [] + if match.group('extension') == 'bz2': + cmdline.append('bzcat') + elif match.group('extension') == 'gz': + cmdline.append('zcat') + else: + cmdline.append('cat') + cmdline.append(input_patch) + cmdline.append('| (cd %s; patch -p1 -f -s -t --no-backup-if-mismatch)' % os.path.join(self.dir, self.orig)) + if os.spawnv(os.P_WAIT, '/bin/sh', ['sh', '-c', ' '.join(cmdline)]): + raise RuntimeError("Can't patch source") + + def debian_patch(self): + name = "orig-" + self.version_dfsg + self.log("Patching source with debian patch (series %s)\n" % name) + fp = file("debian/patches/series/" + name) + series = PatchSeries(name, "debian/patches", fp) + series(dir = os.path.join(self.dir, self.orig)) + + def tar(self): + out = os.path.join("../orig", self.orig_tar) + try: + os.mkdir("../orig") + except OSError: pass + try: + os.stat(out) + raise RuntimeError("Destination already exists") + except OSError: pass + self.log("Generate tarball %s\n" % out) + cmdline = ['tar -czf', out, '-C', self.dir, self.orig] + try: + if os.spawnv(os.P_WAIT, '/bin/sh', ['sh', '-c', ' '.join(cmdline)]): + raise RuntimeError("Can't patch source") + os.chmod(out, 0644) + except: + try: + os.unlink(out) + except OSError: + pass + raise + +if __name__ == '__main__': + from optparse import OptionParser + parser = OptionParser(usage = "%prog [OPTION]... {TAR [PATCH] | REPO}") + parser.add_option("-V", "--override-version", dest = "override_version", help = "Override version", metavar = "VERSION") + options, args = parser.parse_args() + + assert 1 <= len(args) <= 2 + Main(args, options.override_version)() diff --git a/debian/bin/kconfig.py b/debian/bin/kconfig.py new file mode 100644 index 00000000..d5df64f1 --- /dev/null +++ b/debian/bin/kconfig.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import optparse +import os.path +import re +import sys + +from debian_linux.kconfig import * + +def merge(output, configs, overrides): + kconfig = KconfigFile() + for c in configs: + kconfig.read(file(c)) + for key, value in overrides.iteritems(): + kconfig.set(key, value) + file(output, "w").write(str(kconfig)) + +def opt_callback_dict(option, opt, value, parser): + match = re.match('^\s*(\S+)=(\S+)\s*$', value) + if not match: + raise optparse.OptionValueError('not key=value') + dest = option.dest + data = getattr(parser.values, dest) + data[match.group(1)] = match.group(2) + +if __name__ == '__main__': + parser = optparse.OptionParser(usage = "%prog [OPTION]... FILE...") + parser.add_option('-o', '--override', + action='callback', + callback=opt_callback_dict, + default={}, + dest='overrides', + help="Override option", + type='string') + options, args = parser.parse_args() + + merge(args[0], args[1:], options.overrides) diff --git a/debian/bin/patch.apply b/debian/bin/patch.apply new file mode 100644 index 00000000..a4130b93 --- /dev/null +++ b/debian/bin/patch.apply @@ -0,0 +1,227 @@ +#!/usr/bin/env python + +import os, os.path, re, sys +from warnings import warn + +sys.path.append("/usr/share/linux-support-2.6.36-trunk/lib/python") + +from debian_linux.patches import PatchSeries, PatchSeriesList + +_default_home = "/usr/src/kernel-patches/all/2.6.36/debian" +revisions = "orig base 1~experimental.1 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11".split() +upstream = "2.6.36" + +class MatchExtra(object): + def __init__(self, arch, featureset): + self.arch, self.featureset = arch, featureset + + self.matched_arch = self.matched_featureset = False + + def __call__(self, obj): + if not self: + return False + + data = obj.data + + match_arch = [] + match_featureset = [] + for i in data: + if i.startswith("arch="): + match_arch.append(i[5:]) + elif i.startswith("featureset="): + match_featureset.append(i[11:]) + else: + raise RuntimeError('Ignored unknown modifier: %s' % i) + + ret_arch = ret_featureset = False + + if match_arch: + if self.arch is not None: + if self.arch in match_arch: + self.matched_arch = True + ret_arch = True + + else: + ret_arch = True + + if match_featureset: + if self.featureset is not None: + if self.featureset in match_featureset: + self.matched_featureset = True + ret_featureset = True + + else: + ret_featureset = True + + return ret_arch and ret_featureset + + def __nonzero__(self): + return self.arch is not None or self.featureset is not None + + def info(self): + ret = [] + if self.matched_arch: + ret.append("arch=%s" % self.arch) + if self.matched_featureset: + ret.append("featureset=%s" % self.featureset) + return ret + +_marker = object() + +class version_file(object): + _file = 'version.Debian' + extra = None + in_progress = False + + def __init__(self, upstream = None): + if os.path.exists(self._file): + s = file(self._file).readline().strip() + self._read(s) + elif upstream: + warn('No %s file, assuming Debian Linux %s' % (self._file, upstream)) + self.upstream = upstream + self.revision = 'orig' + else: + raise RuntimeError, "Not possible to determine version" + + def __str__(self): + if self.in_progress: + return "unstable" + ret = [self.upstream, self.revision] + if self.extra is not None: + ret.extend(self.extra.info()) + return ' '.join(ret) + + def _read(self, s): + if s == 'unstable': + raise RuntimeError("Tree is in an unstable condition. Can't continue!") + list = s.split() + self.upstream, self.revision = list[0:2] + + arch = featureset = None + for i in list[2:]: + if i.startswith("arch="): + arch = i[5:] + elif i.startswith("featureset="): + featureset = i[11:] + else: + raise RuntimeError("Can't parse extra information") + self.extra = MatchExtra(arch, featureset) + + def _write(self): + if os.path.lexists(self._file): + os.unlink(self._file) + file(self._file, 'w').write('%s\n' % self) + + def begin(self): + self.in_progress = True + self._write() + + def commit(self, revision, extra = _marker): + self.in_progress = False + self.revision = revision + if extra is not _marker: + self.extra = extra + self._write() + +def main(): + options, args = parse_options() + + if len(args) > 1: + print "Too much arguments" + return + + home = options.home + + vfile = version_file(upstream) + current_revision = vfile.revision + current_extra = vfile.extra + + if len(args) == 1: + target_revision = args[0] + else: + target_revision = revisions[-1] + target_extra = MatchExtra(options.arch, options.featureset) + + if vfile.upstream != upstream: + raise RuntimeError("Upstream version differs between tree (%s) and package (%s)" % (vfile.upstream, upstream)) + if current_revision not in revisions: + raise RuntimeError, "Current revision is not in our list of revisions" + if target_revision not in revisions: + raise RuntimeError, "Target revision is not in our list of revisions" + + if current_revision == target_revision and current_extra == target_extra: + print "Nothing to do" + return + + current_index = revisions.index(current_revision) + target_index = revisions.index(target_revision) + + if current_extra: + if current_revision != revisions[-1]: + raise RuntimeError, "Can't patch from %s with options %s" % (current, ' '.join(current_extra)) + consider = ['%s-extra' % i for i in revisions[1:current_index + 1]] + s = PatchSeriesList.read(home, consider) + vfile.begin() + s(cond = current_extra, reverse = True) + vfile.commit(current_revision, None) + + if current_index < target_index: + consider = revisions[current_index + 1:target_index + 1] + s = PatchSeriesList.read(home, consider) + vfile.begin() + s() + vfile.commit(target_revision) + elif current_index > target_index: + consider = revisions[target_index + 1:current_index + 1] + s = PatchSeriesList.read(home, consider) + vfile.begin() + s(reverse = True) + vfile.commit(target_revision) + + if target_extra: + consider = ['%s-extra' % i for i in revisions[1:target_index + 1]] + s = PatchSeriesList.read(home, consider) + vfile.begin() + s(cond = target_extra) + vfile.commit(target_revision, target_extra) + +def parse_options(): + from optparse import OptionParser + parser = OptionParser( + usage = "%prog [OPTION]... [TARGET]", + ) + parser.add_option( + '-a', '--arch', + dest = 'arch', + help = "arch", + ) + parser.add_option( + '-f', '--featureset', + dest = 'featureset', + help = "featureset", + ) + parser.add_option( + '-H', '--overwrite-home', + default = _default_home, dest = 'home', + help = "overwrite home [default: %default]", + ) + + options, args = parser.parse_args() + + if options.arch is None and options.featureset is not None: + raise RuntimeError('You specified a featureset without an arch, this is not really working') + + return options, args + +if __name__ == '__main__': + def showwarning(message, category, filename, lineno): + sys.stderr.write("Warning: %s\n" % message) + import warnings + warnings.showwarning = showwarning + try: + main() + except RuntimeError, e: + sys.stderr.write("Error: %s\n" % e) + raise SystemExit, 1 + diff --git a/debian/bin/perf b/debian/bin/perf new file mode 100644 index 00000000..fc2c0797 --- /dev/null +++ b/debian/bin/perf @@ -0,0 +1,11 @@ +#!/bin/bash + +# Execute the right version of perf for the current kernel. +version="$(uname -r)" +version="${version%%-*}" +shopt -s execfail +exec "perf_$version" "$@" + +# Not found? Tell the user which package to install. +echo >&2 "E: linux-tools-$version is not installed." +exit 1 diff --git a/debian/bin/test-patches b/debian/bin/test-patches new file mode 100644 index 00000000..fdcff209 --- /dev/null +++ b/debian/bin/test-patches @@ -0,0 +1,81 @@ +#!/bin/bash + +set -e +shopt -s extglob + +# Set defaults from the running kernel +arch="$(dpkg --print-architecture)" +kernelabi="$(uname -r)" +ff="${kernelabi#+([^-])-@(trunk|+([0-9]))-}" +if [ "x$ff" != "x$kernelabi" ]; then + flavour="${ff#@(openvz|vserver|xen)-}" + if [ "x$flavour" != "x$ff" ]; then + featureset="${ff%-$flavour}" + else + featureset=none + fi +else + flavour= + featureset=none +fi + +eval "set -- $(getopt -n "$0" -- "f:j:s:" "$@")" +while true; do + case "$1" in + -f) flavour="$2"; shift 2 ;; + -j) export DEBIAN_KERNEL_JOBS="$2"; shift 2 ;; + -s) featureset="$2"; shift 2 ;; + --) shift 1; break ;; + esac +done + +if [ $# -lt 1 ]; then + echo >&2 "Usage: $0 [<options>] <patch>..." + cat >&2 <<EOF +Options: + -f <flavour> specify the 'flavour' of kernel to build, e.g. 686 + -j <jobs> specify number of compiler jobs to run in parallel + -s <featureset> specify an optional featureset to apply, e.g. xen +EOF + exit 2 +fi + +if [ -z "$flavour" ]; then + echo >&2 "You must specify a flavour to build with the -f option" + exit 2 +fi + +dpkg-checkbuilddeps -B + +# Append 'a~test' to Debian version; this should be less than any official +# successor and easily recognisable +version="$(dpkg-parsechangelog | sed 's/^Version: //; t; d')" +if [ "${version%a~test}" = "$version" ]; then + version="$version"a~test + dch -v "$version" --distribution UNRELEASED "Testing patches $*" +fi +debversion="${version##*-}" + +# Copy all patches into a new directory +rm -rf debian/patches/test/ +mkdir debian/patches/test +cp -t debian/patches/test/ "$@" + +# Generate patch series for the new version +>debian/patches/series/"$debversion" +for patch in "$@"; do + echo "+ test/$(basename "$patch")" >>debian/patches/series/"$debversion" +done + +# Regenerate control and included rules +rm debian/control debian/rules.gen +debian/rules debian/control-real && exit 1 || true +test -f debian/control +test -f debian/rules.gen + +# Clean and patch source +debian/rules clean +debian/rules source + +# Build selected binaries +fakeroot make -f debian/rules.gen binary-arch_"$arch"_"$featureset"_"$flavour" |