コード例 #1
0
def apply_patch(patchfile, cwd=None, posix=False, level=0):
    """call 'patch -p[level] [--posix] < arg1'

    posix mode is sometimes necessary. It keeps empty files so that
    dpkg-source removes their contents.

    """
    if not os.path.exists(patchfile):
        raise RuntimeError('patchfile "%s" does not exist' % patchfile)
    fd = open(patchfile, mode='r')

    level_str = '-p%d' % level
    args = ['/usr/bin/patch', level_str]
    if posix:
        args.append('--posix')

    log.info('PATCH COMMAND: %s < %s', ' '.join(args), patchfile)
    log.info('  PATCHING in dir: %s', cwd)
    #    print >> sys.stderr, 'PATCH COMMAND:',' '.join(args),'<',patchfile
    #    print >> sys.stderr, '  PATCHING in dir:',cwd
    res = subprocess.Popen(
        args,
        cwd=cwd,
        stdin=fd,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    returncode = None
    while returncode is None:
        returncode = res.poll()
        ready = select.select([res.stdout, res.stderr], [], [], 0.1)
        # XXX figure out how to do this without reading byte-by-byte
        if res.stdout in ready[0]:
            sys.stdout.write(res.stdout.read(1))
            sys.stdout.flush()
        if res.stderr in ready[0]:
            sys.stderr.write(res.stderr.read(1))
            sys.stderr.flush()
    # finish outputting file
    sys.stdout.write(res.stdout.read())
    sys.stdout.flush()
    sys.stderr.write(res.stderr.read())
    sys.stderr.flush()

    if returncode:
        log.error('ERROR running: %s', ' '.join(args))
        log.error('ERROR in %s', cwd)
        #        print >> sys.stderr, 'ERROR running: %s'%(' '.join(args),)
        #        print >> sys.stderr, 'ERROR in',cwd
        raise RuntimeError('returncode %d' % returncode)
コード例 #2
0
 # Now for each requirement, see if a Debian package satisfies it.
 ops = {'<': '<<', '>': '>>', '==': '=', '<=': '<=', '>=': '>='}
 for req in parsed_reqs:
     reqname = req.project_name.lower()
     gooddebs = set()
     for pydist, debs in dd.get(reqname, {}).iteritems():
         if pydist in req:
             ## log.info("I found Debian packages \"%s\" which provides "
             ##          "Python package \"%s\", version \"%s\", which "
             ##          "satisfies our version requirements: \"%s\""
             ##          % (', '.join(debs), req.project_name, ver, req)
             gooddebs |= (debs)
         else:
             log.info("I found Debian packages \"%s\" which provides "
                      "Python package \"%s\" which "
                      "does not satisfy our version requirements: "
                      "\"%s\" -- ignoring." %
                      (', '.join(debs), req.project_name, req))
     if not gooddebs:
         if on_failure == 'warn':
             log.warn(
                 "I found no Debian package which provides the required "
                 "Python package \"%s\" with version requirements "
                 "\"%s\"." % (req.project_name, req.specs))
         elif on_failure == "raise":
             raise CantSatisfyRequirement(
                 "I found no Debian package which "
                 "provides the required Python package \"%s\" with version "
                 "requirements \"%s\"." % (req.project_name, req.specs),
                 req)
         elif on_failure == "guess":
コード例 #3
0
def build_dsc(
    debinfo,
    dist_dir,
    repackaged_dirname,
    orig_sdist=None,
    patch_posix=0,
    remove_expanded_source_dir=0,
    debian_dir_only=False,
):
    """make debian source package"""
    #    A. Find new dirname and delete any pre-existing contents

    # dist_dir is usually 'deb_dist'

    # the location of the copied original source package (it was
    # re-recreated in dist_dir)
    if debian_dir_only:
        fullpath_repackaged_dirname = os.path.abspath(os.curdir)
    else:
        fullpath_repackaged_dirname = os.path.join(dist_dir,
                                                   repackaged_dirname)

    ###############################################
    # 1. make temporary original source tarball

    #    Note that, for the final tarball, best practices suggest
    #    using "dpkg-source -b".  See
    #    http://www.debian.org/doc/developers-reference/ch-best-pkging-practices.en.html

    # Create the name of the tarball that qualifies as the upstream
    # source. If the original was specified, we'll link to
    # it. Otherwise, we generate our own .tar.gz file from the output
    # of "python setup.py sdist" (done above) so that we avoid
    # packaging .svn directories, for example.

    if not debian_dir_only:
        repackaged_orig_tarball = (
            '%(source)s_%(upstream_version)s.orig.tar.gz' % debinfo.__dict__)
        repackaged_orig_tarball_path = os.path.join(dist_dir,
                                                    repackaged_orig_tarball)
        if orig_sdist is not None:
            if os.path.exists(repackaged_orig_tarball_path):
                os.unlink(repackaged_orig_tarball_path)
            link_func(orig_sdist, repackaged_orig_tarball_path)
        else:
            make_tarball(repackaged_orig_tarball,
                         repackaged_dirname,
                         cwd=dist_dir)

        # apply patch
        if debinfo.patch_file != '':
            apply_patch(debinfo.patch_file,
                        posix=patch_posix,
                        level=debinfo.patch_level,
                        cwd=fullpath_repackaged_dirname)

    for fname in ['Makefile', 'makefile']:
        if os.path.exists(os.path.join(fullpath_repackaged_dirname, fname)):
            sys.stderr.write('*' * 1000 + '\n')
            if debinfo.force_buildsystem:
                sys.stderr.write('WARNING: a Makefile exists in this package. '
                                 'stdeb will tell debhelper 7 to use setup.py '
                                 'to build and install the package, and the '
                                 'Makefile will be ignored. You can disable '
                                 'this behavior with the '
                                 '--force-buildsystem=False argument to the '
                                 'stdeb command.\n')
            else:
                sys.stderr.write(
                    'WARNING: a Makefile exists in this package. '
                    'debhelper 7 will attempt to use this rather '
                    'than setup.py to build and install the '
                    'package. You can disable this behavior with '
                    'the --force-buildsystem=True argument to the '
                    'stdeb command.\n')
            sys.stderr.write('*' * 1000 + '\n')

    ###############################################
    # 2. create debian/ directory and contents
    debian_dir = os.path.join(fullpath_repackaged_dirname, 'debian')
    if not os.path.exists(debian_dir):
        os.mkdir(debian_dir)

    #    A. debian/changelog
    fd = open(os.path.join(debian_dir, 'changelog'), mode='w')
    fd.write("""\
%(source)s (%(full_version)s) %(distname)s; urgency=low

  * source package automatically created by stdeb %(stdeb_version)s

 -- %(maintainer)s  %(date822)s\n""" % debinfo.__dict__)
    fd.close()

    #    B. debian/control
    if debinfo.uploaders:
        debinfo.uploaders = 'Uploaders: %s\n' % ', '.join(debinfo.uploaders)
    else:
        debinfo.uploaders = ''
    control = CONTROL_FILE % debinfo.__dict__
    fd = open(os.path.join(debian_dir, 'control'), mode='w')
    fd.write(control)
    fd.close()

    #    C. debian/rules
    debinfo.percent_symbol = '%'
    rules = RULES_MAIN % debinfo.__dict__

    if debinfo.test_suite:
        rules = rules + RULES_OVERRIDE_DH_AUTO_TEST

    rules = rules.replace('        ', '\t')
    rules_fname = os.path.join(debian_dir, 'rules')
    fd = open(rules_fname, mode='w')
    fd.write(rules)
    fd.close()
    os.chmod(rules_fname, 0755)

    #    D. debian/compat
    fd = open(os.path.join(debian_dir, 'compat'), mode='w')
    fd.write('7\n')
    fd.close()

    #    E. debian/package.mime
    if debinfo.mime_file != '':
        if not os.path.exists(debinfo.mime_file):
            raise ValueError(
                'a MIME file was specified, but does not exist: %s' %
                (debinfo.mime_file, ))
        link_func(debinfo.mime_file,
                  os.path.join(debian_dir, debinfo.package + '.mime'))
    if debinfo.shared_mime_file != '':
        if not os.path.exists(debinfo.shared_mime_file):
            raise ValueError(
                'a shared MIME file was specified, but does not exist: %s' %
                (debinfo.shared_mime_file, ))
        link_func(
            debinfo.shared_mime_file,
            os.path.join(debian_dir, debinfo.package + '.sharedmimeinfo'))

    #    F. debian/copyright
    if debinfo.copyright_file != '':
        link_func(debinfo.copyright_file, os.path.join(debian_dir,
                                                       'copyright'))

    #    H. debian/<package>.install
    if len(debinfo.install_file_lines):
        fd = open(os.path.join(debian_dir, '%s.install' % debinfo.package),
                  mode='w')
        fd.write('\n'.join(debinfo.install_file_lines) + '\n')
        fd.close()

    #    I. debian/<package>.udev
    if debinfo.udev_rules != '':
        fname = debinfo.udev_rules
        if not os.path.exists(fname):
            raise ValueError('udev rules file specified, but does not exist')
        link_func(fname, os.path.join(debian_dir, '%s.udev' % debinfo.package))

    #    J. debian/source/format
    os.mkdir(os.path.join(debian_dir, 'source'))
    fd = open(os.path.join(debian_dir, 'source', 'format'), mode='w')
    fd.write('1.0\n')
    fd.close()

    if debian_dir_only:
        return

    ###############################################
    # 3. unpack original source tarball

    debianized_package_dirname = fullpath_repackaged_dirname + '.debianized'
    if os.path.exists(debianized_package_dirname):
        raise RuntimeError('debianized_package_dirname exists: %s' %
                           debianized_package_dirname)
    #    A. move debianized tree away
    os.rename(fullpath_repackaged_dirname, debianized_package_dirname)
    if orig_sdist is not None:
        #    B. expand repackaged original tarball
        tmp_dir = os.path.join(dist_dir, 'tmp-expand')
        os.mkdir(tmp_dir)
        try:
            expand_tarball(orig_sdist, cwd=tmp_dir)
            orig_tarball_top_contents = os.listdir(tmp_dir)

            # make sure original tarball has exactly one directory
            assert len(orig_tarball_top_contents) == 1
            orig_dirname = orig_tarball_top_contents[0]
            fullpath_orig_dirname = os.path.join(tmp_dir, orig_dirname)

            #    C. move original repackaged tree to .orig
            target = fullpath_repackaged_dirname + '.orig'
            if os.path.exists(target):
                # here from previous invocation, probably
                shutil.rmtree(target)
            os.rename(fullpath_orig_dirname, target)

        finally:
            shutil.rmtree(tmp_dir)

    if 1:
        # check versions of debhelper and python-all
        debhelper_version_str = get_version_str('debhelper')
        if len(debhelper_version_str) == 0:
            log.warn('This version of stdeb requires debhelper >= %s, but you '
                     'do not have debhelper installed. '
                     'Could not check compatibility.' % DH_MIN_VERS)
        else:
            if not dpkg_compare_versions(debhelper_version_str, 'ge',
                                         DH_MIN_VERS):
                log.warn('This version of stdeb requires debhelper >= %s. '
                         'Use stdeb 0.3.x to generate source packages '
                         'compatible with older versions of debhelper.' %
                         (DH_MIN_VERS, ))

        python_defaults_version_str = get_version_str('python-all')
        if len(python_defaults_version_str) == 0:
            log.warn('This version of stdeb requires python-all >= %s, '
                     'but you do not have this package installed. '
                     'Could not check compatibility.' % PYTHON_ALL_MIN_VERS)
        else:
            if not dpkg_compare_versions(python_defaults_version_str, 'ge',
                                         PYTHON_ALL_MIN_VERS):
                log.warn(
                    'This version of stdeb requires python-all >= %s. '
                    'Use stdeb 0.6.0 or older to generate source packages '
                    'that use python-support.' % (PYTHON_ALL_MIN_VERS, ))

    #    D. restore debianized tree
    os.rename(fullpath_repackaged_dirname + '.debianized',
              fullpath_repackaged_dirname)

    #    Re-generate tarball using best practices see
    #    http://www.debian.org/doc/developers-reference/ch-best-pkging-practices.en.html
    #    call "dpkg-source -b new_dirname orig_dirname"
    log.info('CALLING dpkg-source -b %s %s (in dir %s)' %
             (repackaged_dirname, repackaged_orig_tarball, dist_dir))

    dpkg_source('-b',
                repackaged_dirname,
                repackaged_orig_tarball,
                cwd=dist_dir)

    if 1:
        shutil.rmtree(fullpath_repackaged_dirname)

    if not remove_expanded_source_dir:
        # expand the debian source package
        dsc_name = debinfo.source + '_' + debinfo.dsc_version + '.dsc'
        dpkg_source('-x', dsc_name, cwd=dist_dir)
コード例 #4
0
ファイル: cli_runner.py プロジェクト: sephalon/stdeb
def runit(cmd, usage):
    if cmd not in ['sdist_dsc', 'bdist_deb']:
        raise ValueError('unknown command %r' % cmd)
    # process command-line options
    bool_opts = list(map(translate_longopt, stdeb_cmd_bool_opts))
    parser = FancyGetopt(stdeb_cmdline_opts + [
        ('help', 'h', "show detailed help message"),
    ])
    optobj = OptObj()
    args = parser.getopt(object=optobj)
    for option in optobj.__dict__:
        value = getattr(optobj, option)
        is_string = type(value) == str
        if option in bool_opts and is_string:
            setattr(optobj, option, strtobool(value))

    if hasattr(optobj, 'help'):
        print(usage)
        parser.set_option_table(stdeb_cmdline_opts)
        parser.print_help("Options:")
        return 0

    if len(args) != 1:
        log.error('not given single argument (distfile), args=%r', args)
        print(usage)
        return 1

    sdist_file = args[0]

    final_dist_dir = optobj.__dict__.get('dist_dir', 'deb_dist')
    tmp_dist_dir = os.path.join(final_dist_dir, 'tmp_py2dsc')
    if os.path.exists(tmp_dist_dir):
        shutil.rmtree(tmp_dist_dir)
    os.makedirs(tmp_dist_dir)

    if not os.path.isfile(sdist_file):
        log.error("Package %s not found." % sdist_file)
        sys.exit(1)

    patch_file = optobj.__dict__.get('patch_file', None)
    patch_level = int(optobj.__dict__.get('patch_level', 0))
    patch_posix = int(optobj.__dict__.get('patch_posix', 0))

    expand_dir = os.path.join(tmp_dist_dir, 'stdeb_tmp')
    if os.path.exists(expand_dir):
        shutil.rmtree(expand_dir)
    if not os.path.exists(tmp_dist_dir):
        os.mkdir(tmp_dist_dir)
    os.mkdir(expand_dir)

    expand_sdist_file(os.path.abspath(sdist_file), cwd=expand_dir)

    # now the sdist package is expanded in expand_dir
    expanded_root_files = os.listdir(expand_dir)
    assert len(expanded_root_files) == 1
    repackaged_dirname = expanded_root_files[0]
    fullpath_repackaged_dirname = os.path.join(tmp_dist_dir,
                                               repackaged_dirname)
    base_dir = os.path.join(expand_dir, expanded_root_files[0])
    if os.path.exists(fullpath_repackaged_dirname):
        # prevent weird build errors if this dir exists
        shutil.rmtree(fullpath_repackaged_dirname)
    os.renames(base_dir, fullpath_repackaged_dirname)
    del base_dir  # no longer useful

    ##############################################
    if patch_file is not None:
        log.info('py2dsc applying patch %s', patch_file)
        apply_patch(patch_file,
                    posix=patch_posix,
                    level=patch_level,
                    cwd=fullpath_repackaged_dirname)
        patch_already_applied = 1
    else:
        patch_already_applied = 0
    ##############################################

    abs_dist_dir = os.path.abspath(final_dist_dir)

    extra_args = []
    for long in parser.long_opts:
        if long in ['dist-dir=', 'patch-file=']:
            continue  # dealt with by this invocation
        attr = parser.get_attr_name(long).rstrip('=')
        if hasattr(optobj, attr):
            val = getattr(optobj, attr)
            if attr == 'extra_cfg_file':
                val = os.path.abspath(val)
            if long in bool_opts or long.replace('-', '_') in bool_opts:
                extra_args.append('--%s' % long)
            else:
                extra_args.append('--' + long + str(val))

    if patch_already_applied == 1:
        extra_args.append('--patch-already-applied')

    if cmd == 'bdist_deb':
        extra_args.append('bdist_deb')

    args = [
        sys.executable, 'setup.py', '--command-packages', 'stdeb.command',
        'sdist_dsc',
        '--dist-dir=%s' % abs_dist_dir,
        '--use-premade-distfile=%s' % os.path.abspath(sdist_file)
    ] + extra_args

    log.info('-=' * 35 + '-')
    #    print >> sys.stderr, '-='*20
    #    print >> sys.stderr, "Note that the .cfg file(s), if present, have not "\
    #          "been read at this stage. If options are necessary, pass them "\
    #          "from the command line"
    log.info("running the following command in directory: %s\n%s",
             fullpath_repackaged_dirname, ' '.join(args))
    log.info('-=' * 35 + '-')

    try:
        returncode = subprocess.call(
            args,
            cwd=fullpath_repackaged_dirname,
        )
    except Exception:
        log.error('ERROR running: %s', ' '.join(args))
        log.error('ERROR in %s', fullpath_repackaged_dirname)
        raise

    if returncode:
        log.error('ERROR running: %s', ' '.join(args))
        log.error('ERROR in %s', fullpath_repackaged_dirname)
        # log.error('   stderr: %s'res.stderr.read())
        # print >> sys.stderr, 'ERROR running: %s'%(' '.join(args),)
        # print >> sys.stderr, res.stderr.read()
        return returncode
        # raise RuntimeError('returncode %d'%returncode)
    # result = res.stdout.read().strip()

    shutil.rmtree(tmp_dist_dir)
    return returncode