#!/usr/bin/env python import os, os.path, re, sys from warnings import warn sys.path.append("/usr/src/linux-support-@upstream@@abiname@/lib/python") from debian_linux.debian import VersionLinux from debian_linux.patches import PatchSeries, PatchSeriesList _default_home = "@home@" _default_revisions = "@revisions@" _default_source = "@source@" 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:]) 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, ver = None, overwrite = False): if overwrite: self._read(ver) elif os.path.exists(self._file): s = file(self._file).readline().strip() self._read(s) elif ver: warn('No %s file, assuming pristine Linux %s' % (self._file, ver.upstream)) self.version = VersionLinux(ver.upstream + '-0') else: raise RuntimeError, "Not possible to determine version" def __str__(self): if self.in_progress: return "unstable" if self.extra is not None: return ' '.join([str(self.version)] + self.extra.info()) return str(self.version) def _read(self, s): list = s.split() try: self.version = VersionLinux(list[0]) except ValueError: raise RuntimeError, 'Can\'t read version in %s: "%s"' % (self._file, list[0]) arch = featureset = None for i in list[1:]: 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, version, extra = _marker): self.in_progress = False self.version = version 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 revisions = ['0'] + options.revisions.split() source = VersionLinux(options.source) if len(args) == 1: target = VersionLinux(args[0]) else: target = source if options.current is not None: vfile = version_file(options.current, True) else: vfile = version_file(source) current = vfile.version current_extra = vfile.extra target_extra = MatchExtra(options.arch, options.featureset) if current.debian not in revisions: raise RuntimeError, "Current revision is not in our list of revisions" if target.debian not in revisions: raise RuntimeError, "Target revision is not in our list of revisions" if current.debian == target.debian and current_extra == target_extra: print "Nothing to do" return current_index = revisions.index(current.debian) source_index = revisions.index(source.debian) target_index = revisions.index(target.debian) if current_extra: if current_index != source_index: 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, 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) 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) 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, 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( '-C', '--overwrite-current', dest = 'current', help = "overwrite current", ) parser.add_option( '-H', '--overwrite-home', default = _default_home, dest = 'home', help = "overwrite home [default: %default]", ) parser.add_option( '-R', '--overwrite-revisions', default = _default_revisions, dest = 'revisions', help = "overwrite revisions [default: %default]", ) parser.add_option( '-S', '--overwrite-source', default = _default_source, dest = 'source', help = "overwrite source [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