From e28ea0740a7b4eb2ef4c1bd3079d77a40c6072b8 Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Sun, 30 Oct 2011 20:03:33 +0100 Subject: Get rid of the symlink by moving the commands to gbp/scripts/ --- gbp/scripts/import_dsc.py | 344 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 gbp/scripts/import_dsc.py (limited to 'gbp/scripts/import_dsc.py') diff --git a/gbp/scripts/import_dsc.py b/gbp/scripts/import_dsc.py new file mode 100644 index 0000000..94013e2 --- /dev/null +++ b/gbp/scripts/import_dsc.py @@ -0,0 +1,344 @@ +# vim: set fileencoding=utf-8 : +# +# (C) 2006,2007,2011 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 ConfigParser +import sys +import re +import os +import tempfile +import glob +import pipes +import time +from email.Utils import parseaddr +import gbp.command_wrappers as gbpc +from gbp.deb import (debian_version_chars, parse_changelog, + parse_dsc, DscFile, UpstreamSource) +from gbp.git import (build_tag, GitRepository, + GitRepositoryError, rfc822_date_to_git) +from gbp.config import GbpOptionParser, GbpOptionGroup, no_upstream_branch_msg +from gbp.errors import GbpError +import gbp.log + +class SkipImport(Exception): + pass + + +def download_source(pkg, dirs): + if re.match(r'[a-z]{1,5}://', pkg): + mode='dget' + else: + mode='apt-get' + + dirs['download'] = os.path.abspath(tempfile.mkdtemp()) + gbp.log.info("Downloading '%s' using '%s'..." % (pkg, mode)) + if mode == 'apt-get': + gbpc.RunAtCommand('apt-get', + ['-qq', '--download-only', 'source', pkg], + shell=False)(dir=dirs['download']) + else: + gbpc.RunAtCommand('dget', + ['-q', '--download-only', pkg], + shell=False)(dir=dirs['download']) + dsc = glob.glob(os.path.join(dirs['download'], '*.dsc'))[0] + return dsc + + +def apply_patch(diff): + "Apply patch to a source tree" + pipe = pipes.Template() + pipe.prepend('gunzip -c %s' % diff, '.-') + pipe.append('patch -p1 --quiet', '-.') + try: + ret = pipe.copy('', '') + if ret: + gbp.log.err("Error import %s: %d" % (diff, ret)) + return False + except OSError, err: + gbp.log.err("Error importing %s: %s" % (diff, err[0])) + return False + return True + + +def apply_deb_tgz(deb_tgz): + """Apply .debian.tar.gz (V3 source format)""" + gbpc.UnpackTarArchive(deb_tgz, ".")() + return True + + +def apply_debian_patch(repo, unpack_dir, src, options, parents): + """apply the debian patch and tag appropriately""" + try: + os.chdir(unpack_dir) + + if src.diff and not apply_patch(src.diff): + raise GbpError + + if src.deb_tgz and not apply_deb_tgz(src.deb_tgz): + raise GbpError + + if os.path.exists('debian/rules'): + os.chmod('debian/rules', 0755) + os.chdir(repo.path) + + dch = parse_changelog(filename=os.path.join(unpack_dir, 'debian/changelog')) + date= rfc822_date_to_git(dch['Date']) + author, email = parseaddr(dch['Maintainer']) + if not (author and email): + gbp.log.warn("Failed to parse maintainer") + commit = repo.commit_dir(unpack_dir, + "Imported Debian patch %s" % src.version, + branch = options.debian_branch, + other_parents = parents, + author=dict(name=author, email = email, date = date), + committer=dict(name=[None, author][options.author_committer], + email=[None, email][options.author_committer], + date=[None, date][options.author_committer_date])) + repo.create_tag(build_tag(options.debian_tag, src.version), + msg="Debian release %s" % src.version, + commit=commit, + sign=options.sign_tags, + keyid=options.keyid) + except gbpc.CommandExecFailed: + gbp.log.err("Failed to import Debian package") + raise GbpError + finally: + os.chdir(repo.path) + + +def print_dsc(dsc): + if dsc.native: + gbp.log.debug("Debian Native Package %s") + gbp.log.debug("Version: %s" % dsc.upstream_version) + gbp.log.debug("Debian tarball: %s" % dsc.tgz) + else: + gbp.log.debug("Upstream version: %s" % dsc.upstream_version) + gbp.log.debug("Debian version: %s" % dsc.debian_version) + gbp.log.debug("Upstream tarball: %s" % dsc.tgz) + if dsc.diff: + gbp.log.debug("Debian patch: %s" % dsc.diff) + if dsc.deb_tgz: + gbp.log.debug("Debian patch: %s" % dsc.deb_tgz) + if dsc.epoch: + gbp.log.debug("Epoch: %s" % dsc.epoch) + + +def move_tag_stamp(repo, format, version): + "Move tag out of the way appending the current timestamp" + old = build_tag(format, version) + timestamped = "%s~%s" % (version, int(time.time())) + new = build_tag(format, timestamped) + repo.move_tag(old, new) + + +def set_bare_repo_options(options): + """Modify options for import into a bare repository""" + if options.pristine_tar: + gbp.log.info("Bare repository: setting %s option" + % (["", " '--no-pristine-tar'"][options.pristine_tar], )) + options.pristine_tar = False + + +def parse_args(argv): + try: + parser = GbpOptionParser(command=os.path.basename(argv[0]), prefix='', + usage='%prog [options] /path/to/package.dsc') + except ConfigParser.ParsingError, err: + gbp.log.err(err) + return None, None + + import_group = GbpOptionGroup(parser, "import options", + "pristine-tar and filtering") + tag_group = GbpOptionGroup(parser, "tag options", + "options related to git tag creation") + branch_group = GbpOptionGroup(parser, "version and branch naming options", + "version number and branch layout options") + + for group in [import_group, branch_group, tag_group ]: + parser.add_option_group(group) + + parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, + help="verbose command execution") + parser.add_config_file_option(option_name="color", dest="color", type='tristate') + parser.add_option("--download", action="store_true", dest="download", default=False, + help="download source package") + branch_group.add_config_file_option(option_name="debian-branch", + dest="debian_branch") + branch_group.add_config_file_option(option_name="upstream-branch", + dest="upstream_branch") + branch_group.add_boolean_config_file_option(option_name="create-missing-branches", + dest="create_missing_branches") + + tag_group.add_boolean_config_file_option(option_name="sign-tags", + dest="sign_tags") + tag_group.add_config_file_option(option_name="keyid", + dest="keyid") + tag_group.add_config_file_option(option_name="debian-tag", + dest="debian_tag") + tag_group.add_config_file_option(option_name="upstream-tag", + dest="upstream_tag") + + import_group.add_config_file_option(option_name="filter", + dest="filters", action="append") + import_group.add_boolean_config_file_option(option_name="pristine-tar", + dest="pristine_tar") + import_group.add_option("--allow-same-version", action="store_true", + dest="allow_same_version", default=False, + help="allow to import already imported version") + import_group.add_boolean_config_file_option(option_name="author-is-committer", + dest="author_committer") + import_group.add_boolean_config_file_option(option_name="author-date-is-committer-date", + dest="author_committer_date") + + (options, args) = parser.parse_args(argv[1:]) + gbp.log.setup(options.color, options.verbose) + return options, args + + +def main(argv): + dirs = dict(top=os.path.abspath(os.curdir)) + needs_repo = False + ret = 0 + skipped = False + parents = None + + options, args = parse_args(argv) + + try: + if len(args) != 1: + gbp.log.err("Need to give exactly one package to import. Try --help.") + raise GbpError + else: + pkg = args[0] + if options.download: + dsc = download_source(pkg, dirs=dirs) + else: + dsc = pkg + + src = parse_dsc(dsc) + if src.pkgformat not in [ '1.0', '3.0' ]: + raise GbpError, "Importing %s source format not yet supported." % src.pkgformat + 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: + gbp.log.err("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: + gbp.log.info("No git repository found, creating one.") + repo = GitRepository.create(src.pkg) + os.chdir(repo.path) + + if repo.bare: + set_bare_repo_options(options) + + dirs['tmp'] = os.path.abspath(tempfile.mkdtemp(dir='..')) + upstream = UpstreamSource(src.tgz) + upstream.unpack(dirs['tmp'], options.filters) + + 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 repo.find_version(options.debian_tag, src.version): + gbp.log.warn("Version %s already imported." % src.version) + if options.allow_same_version: + gbp.log.info("Moving tag of version '%s' since import forced" % src.version) + move_tag_stamp(repo, options.debian_tag, src.version) + else: + raise SkipImport + + if not repo.find_version(format[0], src.upstream_version): + gbp.log.info("Tag %s not found, importing %s tarball" % (tag, format[1])) + if is_empty: + branch = None + else: + branch = [options.upstream_branch, + options.debian_branch][src.native] + if not repo.has_branch(branch): + if options.create_missing_branches: + gbp.log.info("Creating missing branch '%s'" % branch) + repo.create_branch(branch) + else: + gbp.log.err(no_upstream_branch_msg % branch + + "\nAlso check the --create-missing-branches option.") + raise GbpError + + commit = repo.commit_dir(upstream.unpacked, + "Imported %s" % msg, + branch) + repo.create_tag(name=tag, + msg=msg, + commit=commit, + sign=options.sign_tags, + keyid=options.keyid) + if not src.native: + if is_empty: + repo.create_branch(options.upstream_branch, commit) + if options.pristine_tar: + gbpc.PristineTar().commit(src.tgz, 'refs/heads/%s' % options.upstream_branch) + parents = [ options.upstream_branch ] + if not src.native: + if is_empty and not repo.has_branch(options.debian_branch): + repo.create_branch(options.debian_branch, commit) + if src.diff or src.deb_tgz: + apply_debian_patch(repo, upstream.unpacked, src, options, parents) + else: + gbp.log.warn("Didn't find a diff to apply.") + if repo.get_branch() == options.debian_branch or is_empty: + # Update HEAD if we modified the checked out branch + repo.force_head(options.debian_branch, hard=True) + except KeyboardInterrupt: + ret = 1 + gbp.log.err("Interrupted. Aborting.") + except gbpc.CommandExecFailed: + ret = 1 + except GitRepositoryError, msg: + gbp.log.err("Git command failed: %s" % msg) + ret = 1 + except GbpError, err: + if len(err.__str__()): + gbp.log.err(err) + ret = 1 + except SkipImport: + skipped = True + finally: + os.chdir(dirs['top']) + + for d in [ 'tmp', 'download' ]: + if dirs.has_key(d): + gbpc.RemoveTree(dirs[d])() + + if not ret and not skipped: + gbp.log.info("Version '%s' imported under '%s'" % (src.version, 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\:·: -- cgit v1.2.3