# vim: set fileencoding=utf-8 : # # (C) 2008, 2009, 2010, 2017 Guido Günther # 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, please see # """Import multiple dsc files into Git in one go""" import glob import os import sys import tempfile import gbp.command_wrappers as gbpc from gbp.deb import DpkgCompareVersions from gbp.deb.dscfile import DscFile from gbp.errors import GbpError from gbp.git import GitRepository, GitRepositoryError from gbp.scripts import import_dsc from gbp.config import GbpOptionParser import gbp.log class DscCompareVersions(DpkgCompareVersions): def __init__(self): DpkgCompareVersions.__init__(self) def __call__(self, dsc1, dsc2): return DpkgCompareVersions.__call__(self, dsc1.version, dsc2.version) def cmp_to_key(mycmp): 'Convert a cmp= function into a key= function' class K(object): def __init__(self, obj, *args): self.obj = obj def __lt__(self, other): return mycmp(self.obj, other.obj) < 0 def __gt__(self, other): return mycmp(self.obj, other.obj) > 0 def __eq__(self, other): return mycmp(self.obj, other.obj) == 0 def __le__(self, other): return mycmp(self.obj, other.obj) <= 0 def __ge__(self, other): return mycmp(self.obj, other.obj) >= 0 def __ne__(self, other): return mycmp(self.obj, other.obj) != 0 return K class GitImportDsc(object): def __init__(self, args): self.args = args def importdsc(self, dsc): return import_dsc.main(['import-dsc'] + self.args + [dsc.dscfile]) def fetch_snapshots(pkg, downloaddir): "Fetch snapshots using debsnap from snapshots.debian.org" dscs = None gbp.log.info("Downloading snapshots of '%s' to '%s'..." % (pkg, downloaddir)) debsnap = gbpc.Command("debsnap", ['--force', '--destdir=%s' % (downloaddir), pkg]) try: debsnap(quiet=True) except gbpc.CommandExecFailed as e: if debsnap.retcode == 2: gbp.log.err(e) gbp.log.warn("Some packages failed to download. Continuing.") pass else: raise dscs = glob.glob(os.path.join(downloaddir, '*.dsc')) if not dscs: raise GbpError('No package downloaded') return [os.path.join(downloaddir, dsc) for dsc in dscs] def set_gbp_conf_files(): """ Filter out all gbp.conf files that are local to the git repository and set GBP_CONF_FILES accordingly so gbp import-dsc will only use these. """ global_config = GbpOptionParser.get_config_files(no_local=True) gbp_conf_files = ':'.join(global_config) os.environ['GBP_CONF_FILES'] = gbp_conf_files gbp.log.debug("Setting GBP_CONF_FILES to '%s'" % gbp_conf_files) def print_help(): print("""Usage: gbp import-dscs [options] [gbp-import-dsc options] /path/to/dsc1 [/path/to/dsc2] ... gbp import-dscs --debsnap [options] [gbp-import-dsc options] package Options: --debsnap: use debsnap command to download packages --ignore-repo-config ignore gbp.conf in git repo """) def main(argv): dirs = dict(top=os.path.abspath(os.curdir)) dscs = [] ret = 0 verbose = False dsc_key = cmp_to_key(DscCompareVersions()) use_debsnap = False try: import_args = argv[1:] if '--verbose' in import_args: verbose = True gbp.log.setup(False, verbose) if '--ignore-repo-config' in import_args: set_gbp_conf_files() import_args.remove('--ignore-repo-config') # Not using Configparser since we want to pass all unknown options # unaltered to gbp import-dsc if '--debsnap' in import_args: use_debsnap = True import_args.remove('--debsnap') if import_args == []: print_help() raise GbpError pkg = import_args[-1] import_args = import_args[:-1] else: for arg in argv[::-1]: if arg.endswith('.dsc'): dscs.append(DscFile.parse(arg)) import_args.remove(arg) if not use_debsnap and not dscs: print_help() raise GbpError if use_debsnap: dirs['tmp'] = os.path.abspath(tempfile.mkdtemp()) dscs = [DscFile.parse(f) for f in fetch_snapshots(pkg, dirs['tmp'])] dscs.sort(key=dsc_key) importer = GitImportDsc(import_args) try: repo = GitRepository('.') (clean, out) = repo.is_clean() if not clean: gbp.log.err("Repository has uncommitted changes, " "commit these first: ") raise GbpError(out) else: dirs['pkg'] = dirs['top'] except GitRepositoryError: # no git repository there yet dirs['pkg'] = os.path.join(dirs['top'], dscs[0].pkg) if importer.importdsc(dscs[0]): raise GbpError("Failed to import '%s'" % dscs[0].dscfile) os.chdir(dirs['pkg']) for dsc in dscs[1:]: if importer.importdsc(dsc): raise GbpError("Failed to import '%s'" % dscs[0].dscfile) except KeyboardInterrupt: ret = 1 gbp.log.err("Interrupted. Aborting.") except (GbpError, gbpc.CommandExecFailed, GitRepositoryError) as err: if str(err): gbp.log.err(err) ret = 1 finally: if 'tmp' in dirs: gbpc.RemoveTree(dirs['tmp'])() os.chdir(dirs['top']) if not ret: gbp.log.info('Everything imported under %s' % dirs['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\:·: