#!/usr/bin/python -u # vim: set fileencoding=utf-8 : # # (C) 2006,2007 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 """Import a Debian source package into a git repository""" import sys import re import os import tempfile import glob import pipes from email.Utils import parseaddr import gbp.command_wrappers as gbpc from gbp.deb_utils import debian_version_chars, parse_changelog, unpack_orig, parse_dsc, DscFile, tar_toplevel from gbp.git_utils import build_tag, create_repo, GitRepository, GitRepositoryError, rfc822_date_to_git from gbp.config import GbpOptionParser from gbp.errors import GbpError def git_apply_patch(diff): "Import patch via git apply" pipe = pipes.Template() pipe.prepend('gunzip -c %s' % diff, '.-') pipe.append('git apply --index --apply --whitespace=nowarn -', '-.') try: ret = pipe.copy('', '') if ret: print >>sys.stderr, "Error import %s: %d" % (diff, ret) return False except OSError, err: print >>sys.stderr, "Error importing %s: %s" % (diff, err[0]) return False return True def apply_debian_patch(repo, src, options): """apply the debian patch and tag appropriately""" version = "%s-%s" % (src.upstream_version, src.debian_version) gitTag = gbpc.GitTag(options.sign_tags, options.keyid) try: if src.diff and not git_apply_patch(src.diff): raise GbpError os.chmod('debian/rules', 0755) if not repo.is_clean()[0]: dch = parse_changelog('debian/changelog') env = { 'GIT_AUTHOR_DATE': rfc822_date_to_git(dch['Date']) } name, addr = parseaddr(dch['Maintainer']) if name and addr: env['GIT_AUTHOR_NAME'] = name env['GIT_AUTHOR_EMAIL'] = addr else: print >>sys.stderr, "Warning: failed to parse maintainer" gbpc.GitCommitAll(extra_env=env)(msg="Imported Debian patch %s" % version) else: print "Nothing to commit, nothing imported." gitTag(build_tag(options.debian_tag, version), msg="Debian release %s" % version) except gbpc.CommandExecFailed: print >>sys.stderr, "Failed to import Debian package" raise GbpError def print_dsc(dsc): 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 if dsc.epoch: print "Epoch: %s" % dsc.epoch def main(argv): dirs = {'top': os.path.abspath(os.curdir)} needs_repo = False ret = 0 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="debian-branch", dest="debian_branch") parser.add_config_file_option(option_name="upstream-branch", dest="upstream_branch") parser.add_option("--no-merge", dest='merge', action="store_false", default=True, help="after import dont do any merging to another branch") parser.add_boolean_config_file_option(option_name="sign-tags", dest="sign_tags") parser.add_config_file_option(option_name="keyid", dest="keyid") parser.add_config_file_option(option_name="debian-tag", dest="debian_tag") parser.add_config_file_option(option_name="upstream-tag", dest="upstream_tag") parser.add_config_file_option(option_name="filter", dest="filters", action="append") parser.add_boolean_config_file_option(option_name="pristine-tar", dest="pristine_tar") (options, args) = parser.parse_args(argv[1:]) if options.verbose: gbpc.Command.verbose = True gitTag = gbpc.GitTag(options.sign_tags, options.keyid) try: if len(args) != 1: parser.print_help() raise GbpError else: src = parse_dsc(args[0]) if options.verbose: print_dsc(src) try: repo = GitRepository('.') is_empty = repo.is_empty() (clean, out) = repo.is_clean() if not clean and not is_empty: print >>sys.stderr, "Repository has uncommitted changes, commit these first: " raise GbpError, out except GitRepositoryError: # no repo found, create one needs_repo = True is_empty = True if needs_repo: print "No git repository found, creating one." repo = create_repo(src.pkg) os.chdir(repo.path) dirs['tmp'] = os.path.abspath(tempfile.mkdtemp(dir='..')) unpack_dir = unpack_orig(src.tgz, dirs['tmp'], options.filters) unpack_dir = tar_toplevel(unpack_dir) format = [(options.upstream_tag, "Upstream"), (options.debian_tag, "Debian")][src.native] tag = build_tag(format[0], src.upstream_version) msg = "%s version %s" % (format[1], src.upstream_version) if not repo.has_tag(tag): print "tag %s not found, importing %s tarball" % (tag, format[1]) # FIXME: this is what import-orig does - merge if not is_empty: if src.native: repo.set_branch(options.debian_branch) else: repo.set_branch(options.upstream_branch) repo.replace_tree(unpack_dir, options.filters, verbose=True) gbpc.GitCommitAll()(msg="Imported %s" % msg) gitTag(tag, msg=msg) if not src.native and is_empty: gbpc.GitBranch()(options.upstream_branch) if options.pristine_tar and not src.native: gbpc.PristineTar().commit(src.tgz, 'refs/heads/%s' % options.upstream_branch) if not src.native: if is_empty and not repo.has_branch(options.debian_branch): gbpc.GitBranch()(options.debian_branch) repo.set_branch(options.debian_branch) if options.merge: print "Merging to %s" % options.debian_branch try: gbpc.GitMerge(options.upstream_branch)() except gbpc.CommandExecFailed: raise GbpError, """Merge of %s failed, please resolve manually""" % options.upstream_branch repo.replace_tree(unpack_dir, options.filters) apply_debian_patch(repo, src, options) except gbpc.CommandExecFailed: os.chdir(dirs['top']) ret = 1 except GbpError, err: if len(err.__str__()): print >>sys.stderr, err os.chdir(dirs['top']) ret = 1 if dirs.has_key('tmp'): gbpc.RemoveTree(dirs['tmp'])() if not ret: print "Everything imported under '%s'" % src.pkg return ret if __name__ == '__main__': sys.exit(main(sys.argv)) # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: