#!/usr/bin/python # -*- coding: utf-8 -*- # # # (C) 2006 Guido Guenther # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """make a git archive out of a Debian source package""" import sys import re import os import tempfile import glob import git_buildpackage from git_buildpackage.deb_utils import debian_version_chars from git_buildpackage.git_utils import sanitize_version from git_buildpackage.config import GBPOptionParser class DscFile(object): """Keeps all needed data read from a dscfile""" pkg_re = re.compile('Source:\s+(?P.+)\s*') version_re = re.compile("Version:\s(\d+\:)?(?P[%s]+)\s*$" % debian_version_chars) tar_re = re.compile('^\s\w+\s\d+\s+(?P[^_]+_[^_]+(\.orig)?\.tar\.(gz|bz2))') def __init__(self, dscfile): self.dscfile = os.path.abspath(dscfile) f = file(self.dscfile) for line in f: m = self.version_re.match(line) if m: if '-' in m.group('version'): self.debian_version = m.group('version').split("-")[-1] self.upstream_version = "-".join(m.group('version').split("-")[0:-1]) self.native = False else: self.native = True # Debian native package self.upstream_version = m.group('version') continue m = self.pkg_re.match(line) if m: self.pkg = m.group('pkg') continue m = self.tar_re.match(line) if m: fromdir = os.path.dirname(dscfile) self.tgz = os.path.join(fromdir, m.group('tar')) continue f.close() def parse_dsc(dscfile): """parse dsc by creating a DscFile object""" try: dsc = DscFile(dscfile) except IOError, err: print >>sys.stderr, "Error reading dsc file: %s" % err dsc = None else: try: if dsc.native: print "Debian Native Package" print "Version:", dsc.upstream_version else: print "Upstream version:", dsc.upstream_version print "Debian version:", dsc.debian_version except AttributeError: print >>sys.stderr, "Error parsing dsc file %s" % dscfile dsc = None return dsc def import_upstream(src, dirs, upstream_branch, tagger): """ import a new upstream version on the upstream branch and tag appropriately """ try: unpackTGZ = git_buildpackage.UnpackTGZ(src.tgz, dirs['tmp']) unpackTGZ() except git_buildpackage.CommandExecFailed: print >>sys.stderr,"Unpacking of %s failed" % src.tgz git_buildpackage.RemoveTree(dirs['tmp'])() return False try: dirs['git'] = glob.glob('%s/*' % unpackTGZ.dir)[0] os.chdir(dirs['git']) git_buildpackage.GitInitDB()() git_buildpackage.GitAdd()(['.']) git_buildpackage.GitCommitAll()( msg="Imported %s version %s" % (['upstream', 'Debian'][src.native], src.upstream_version)) tagger(sanitize_version(src.upstream_version)) if not src.native: git_buildpackage.GitBranch()(upstream_branch) except git_buildpackage.CommandExecFailed: print >>sys.stderr,"Creation of git repository failed" git_buildpackage.RemoveTree(unpackTGZ.dir)() return False return True def apply_debian_patch(src, dirs, tagger): """apply the debian patch and tag appropriately""" try: git_buildpackage.DpkgSourceExtract()(src.dscfile, dirs['dpkg-src']) os.chdir(dirs['git']) git_buildpackage.GitLoadDirs()(dirs['dpkg-src'], 'Imported Debian patch') tagger(sanitize_version('%s-%s' % (src.upstream_version, src.debian_version))) except git_buildpackage.CommandExecFailed: print >>sys.stderr,"Failed to import Debian package" return False return True def move_tree(src, dirs): """rename the temporary unpack directory to it's final name""" try: os.rename(dirs['git'], src.pkg) except OSError, err: print >>sys.stderr, "Cannot move git repository '%s' to it's final location '%s': %s" % (dirs['git'], os.path.abspath(src.pkg), err) return False else: git_buildpackage.RemoveTree(dirs['tmp'])() return True def main(argv): dirs = {'top': os.path.abspath(os.curdir)} parser = GBPOptionParser(command=os.path.basename(argv[0]), prefix='', usage='%prog [options] /path/to/package.dsc') parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="verbose command execution") parser.add_config_file_option(option_name="upstream-branch", dest="upstream_branch", help="upstream branch, default is '%(upstream-branch)s'") parser.add_config_file_option(option_name="sign-tags", dest="sign_tags", help="sign git tags", action="store_true") parser.add_config_file_option(option_name="keyid", dest="keyid", help="GPG keyid to sign tags with") (options, args) = parser.parse_args(argv[1:]) if options.verbose: git_buildpackage.Command.verbose = True gitTag = git_buildpackage.GitTag(options.sign_tags, options.keyid) if len(args) != 1: parser.print_help() return 1 else: src = parse_dsc(args[0]) if not src: return 1 dirs['tmp'] = os.path.abspath(tempfile.mkdtemp(dir='.')) if not import_upstream(src, dirs, options.upstream_branch, gitTag): return 1 os.chdir(dirs['top']) if not src.native: dirs['unpack'] = os.path.join(dirs['tmp'], 'unpack') os.mkdir(dirs['unpack']) dirs['dpkg-src'] = os.path.join(dirs['unpack'], "%s-%s-%s" % (src.pkg, src.upstream_version, src.debian_version)) if not apply_debian_patch(src, dirs, gitTag): return 1 os.chdir(dirs['top']) if not move_tree(src, dirs): return 1 print 'Everything imported under %s' % src.pkg if __name__ == '__main__': sys.exit(main(sys.argv)) # vim:et:ts=4:sw=4: