From 82f61bba7f0a4bb18a6045718b1f500605e448e7 Mon Sep 17 00:00:00 2001 From: Florian Festi Date: Jun 13 2016 14:06:01 +0000 Subject: - Add new Python dependency generator (provides only for now) (#1340885) --- diff --git a/rpm-4.13.x-pythondistdeps-Makefile.patch b/rpm-4.13.x-pythondistdeps-Makefile.patch new file mode 100644 index 0000000..dfdaf00 --- /dev/null +++ b/rpm-4.13.x-pythondistdeps-Makefile.patch @@ -0,0 +1,20 @@ +--- rpm-4.13.0-rc1/scripts/Makefile.am.orig 2015-09-01 19:45:43.896822977 +0200 ++++ rpm-4.13.0-rc1/scripts/Makefile.am 2016-06-13 15:46:34.281390084 +0200 +@@ -11,7 +11,7 @@ + check-files check-prereqs \ + check-buildroot check-rpaths check-rpaths-worker \ + find-debuginfo.sh find-lang.sh \ +- perl.prov perl.req pythondeps.sh \ ++ perl.prov perl.req pythondeps.sh pythondistdeps.py \ + rpmdb_loadcvt rpm.daily rpm.log rpm.supp rpm2cpio.sh \ + tgpg vpkg-provides.sh \ + find-requires find-provides \ +@@ -30,7 +30,7 @@ + check-files check-prereqs \ + check-buildroot check-rpaths check-rpaths-worker \ + find-lang.sh find-requires find-provides \ +- perl.prov perl.req pythondeps.sh \ ++ perl.prov perl.req pythondeps.sh pythondistdeps.py \ + mono-find-requires mono-find-provides \ + pkgconfigdeps.sh libtooldeps.sh \ + ocaml-find-requires.sh ocaml-find-provides.sh \ diff --git a/rpm-4.13.x-pythondistdeps-fileattr.patch b/rpm-4.13.x-pythondistdeps-fileattr.patch new file mode 100644 index 0000000..fcf9762 --- /dev/null +++ b/rpm-4.13.x-pythondistdeps-fileattr.patch @@ -0,0 +1,8 @@ +--- rpm-4.13.0-rc1/fileattrs/python.attr.orig 2016-06-13 15:49:10.072832164 +0200 ++++ rpm-4.13.0-rc1/fileattrs/python.attr 2016-06-13 15:50:46.687106846 +0200 +@@ -1,4 +1,4 @@ +-%__python_provides %{_rpmconfigdir}/pythondeps.sh --provides ++%__python_provides %{_rpmconfigdir}/pythondistdeps.py --provides + %__python_requires %{_rpmconfigdir}/pythondeps.sh --requires + %__python_path ^((/usr/lib(64)?/python[[:digit:]]\\.[[:digit:]]/.*\\.(py[oc]?|so))|(%{_bindir}/python[[:digit:]]\\.[[:digit:]]))$ + %__python_magic [Pp]ython.*(executable|byte-compiled) diff --git a/rpm-4.13.x-pythondistdeps.patch b/rpm-4.13.x-pythondistdeps.patch new file mode 100644 index 0000000..695393c --- /dev/null +++ b/rpm-4.13.x-pythondistdeps.patch @@ -0,0 +1,229 @@ +diff --git a/scripts/pythondistdeps.py b/scripts/pythondistdeps.py +new file mode 100755 +index 0000000..8a2f43d +--- /dev/null ++++ b/scripts/pythondistdeps.py +@@ -0,0 +1,223 @@ ++#!/usr/bin/python ++# -*- coding: utf-8 -*- ++# ++# Copyright 2010 Per Øyvind Karlsen ++# Copyright 2015 Neal Gompa ++# ++# This program is free software. It may be redistributed and/or modified under ++# the terms of the LGPL version 2.1 (or later). ++# ++# RPM python dependency generator, using .egg-info/.egg-link/.dist-info data ++# ++ ++from __future__ import print_function ++from getopt import getopt ++from os.path import basename, dirname, isdir, sep ++from sys import argv, stdin, version ++from distutils.sysconfig import get_python_lib ++ ++ ++opts, args = getopt( ++ argv[1:], 'hPRrCEMLl:', ++ ['help', 'provides', 'requires', 'recommends', 'conflicts', 'extras', 'majorver-provides', 'legacy-provides' , 'legacy']) ++ ++Provides = False ++Requires = False ++Recommends = False ++Conflicts = False ++Extras = False ++Provides_PyMajorVer_Variant = False ++legacy_Provides = False ++legacy = False ++ ++for o, a in opts: ++ if o in ('-h', '--help'): ++ print('-h, --help\tPrint help') ++ print('-P, --provides\tPrint Provides') ++ print('-R, --requires\tPrint Requires') ++ print('-r, --recommends\tPrint Recommends') ++ print('-C, --conflicts\tPrint Conflicts') ++ print('-E, --extras\tPrint Extras ') ++ print('-M, --majorver-provides\tPrint extra Provides with Python major version only') ++ print('-L, --legacy-provides\tPrint extra legacy pythonegg Provides') ++ print('-l, --legacy\tPrint legacy pythonegg Provides/Requires instead') ++ exit(1) ++ elif o in ('-P', '--provides'): ++ Provides = True ++ elif o in ('-R', '--requires'): ++ Requires = True ++ elif o in ('-r', '--recommends'): ++ Recommends = True ++ elif o in ('-C', '--conflicts'): ++ Conflicts = True ++ elif o in ('-E', '--extras'): ++ Extras = True ++ elif o in ('-M', '--majorver-provides'): ++ Provides_PyMajorVer_Variant = True ++ elif o in ('-L', '--legacy-provides'): ++ legacy_Provides = True ++ elif o in ('-l', '--legacy'): ++ legacy = True ++ ++if Requires: ++ py_abi = True ++else: ++ py_abi = False ++py_deps = {} ++if args: ++ files = args ++else: ++ files = stdin.readlines() ++ ++for f in files: ++ f = f.strip() ++ lower = f.lower() ++ name = 'python(abi)' ++ # add dependency based on path, versioned if within versioned python directory ++ if py_abi and (lower.endswith('.py') or lower.endswith('.pyc') or lower.endswith('.pyo')): ++ if name not in py_deps: ++ py_deps[name] = [] ++ purelib = get_python_lib(standard_lib=1, plat_specific=0).split(version[:3])[0] ++ platlib = get_python_lib(standard_lib=1, plat_specific=1).split(version[:3])[0] ++ for lib in (purelib, platlib): ++ if lib in f: ++ spec = ('==', f.split(lib)[1].split(sep)[0]) ++ if spec not in py_deps[name]: ++ py_deps[name].append(spec) ++ ++ # XXX: hack to workaround RPM internal dependency generator not passing directories ++ lower_dir = dirname(lower) ++ if lower_dir.endswith('.egg') or \ ++ lower_dir.endswith('.egg-info') or \ ++ lower_dir.endswith('.egg-link') or \ ++ lower_dir.endswith('.dist-info'): ++ lower = lower_dir ++ f = dirname(f) ++ # Determine provide, requires, conflicts & recommends based on egg/dist metadata ++ if lower.endswith('.egg') or \ ++ lower.endswith('.egg-info') or \ ++ lower.endswith('.egg-link') or \ ++ lower.endswith('.dist-info'): ++ # This import is very slow, so only do it if needed ++ from pkg_resources import Distribution, FileMetadata, PathMetadata ++ dist_name = basename(f) ++ if isdir(f): ++ path_item = dirname(f) ++ metadata = PathMetadata(path_item, f) ++ else: ++ path_item = f ++ metadata = FileMetadata(f) ++ dist = Distribution.from_location(path_item, dist_name, metadata) ++ if (Provides_PyMajorVer_Variant or legacy_Provides or legacy) and Provides: ++ # Get the Python major version ++ pyver_major = dist.py_version.split('.')[0] ++ if Provides: ++ # If egg/dist metadata says package name is python, we provide python(abi) ++ if dist.key == 'python': ++ name = 'python(abi)' ++ if name not in py_deps: ++ py_deps[name] = [] ++ py_deps[name].append(('==', dist.py_version)) ++ if not legacy: ++ name = 'python{}dist({})'.format(dist.py_version, dist.key) ++ if name not in py_deps: ++ py_deps[name] = [] ++ if Provides_PyMajorVer_Variant: ++ pymajor_name = 'python{}dist({})'.format(pyver_major, dist.key) ++ if pymajor_name not in py_deps: ++ py_deps[pymajor_name] = [] ++ if legacy or legacy_Provides: ++ legacy_name = 'pythonegg({})({})'.format(pyver_major, dist.key) ++ if legacy_name not in py_deps: ++ py_deps[legacy_name] = [] ++ if dist.version: ++ spec = ('==', dist.version) ++ if spec not in py_deps[name]: ++ if not legacy: ++ py_deps[name].append(spec) ++ if Provides_PyMajorVer_Variant: ++ py_deps[pymajor_name].append(spec) ++ if legacy or legacy_Provides: ++ py_deps[legacy_name].append(spec) ++ if Requires or (Recommends and dist.extras): ++ name = 'python(abi)' ++ # If egg/dist metadata says package name is python, we don't add dependency on python(abi) ++ if dist.key == 'python': ++ py_abi = False ++ if name in py_deps: ++ py_deps.pop(name) ++ elif py_abi and dist.py_version: ++ if name not in py_deps: ++ py_deps[name] = [] ++ spec = ('==', dist.py_version) ++ if spec not in py_deps[name]: ++ py_deps[name].append(spec) ++ deps = dist.requires() ++ if Recommends: ++ depsextras = dist.requires(extras=dist.extras) ++ if not Requires: ++ for dep in reversed(depsextras): ++ if dep in deps: ++ depsextras.remove(dep) ++ deps = depsextras ++ # add requires/recommends based on egg/dist metadata ++ for dep in deps: ++ if legacy: ++ name = 'pythonegg({})({})'.format(pyver_major, dep.key) ++ else: ++ name = 'python{}dist({})'.format(dist.py_version, dep.key) ++ for spec in dep.specs: ++ if spec[0] != '!=': ++ if name not in py_deps: ++ py_deps[name] = [] ++ if spec not in py_deps[name]: ++ py_deps[name].append(spec) ++ if not dep.specs: ++ py_deps[name] = [] ++ # Unused, for automatic sub-package generation based on 'extras' from egg/dist metadata ++ # TODO: implement in rpm later, or...? ++ if Extras: ++ deps = dist.requires() ++ extras = dist.extras ++ print(extras) ++ for extra in extras: ++ print('%%package\textras-{}'.format(extra)) ++ print('Summary:\t{} extra for {} python package'.format(extra, dist.key)) ++ print('Group:\t\tDevelopment/Python') ++ depsextras = dist.requires(extras=[extra]) ++ for dep in reversed(depsextras): ++ if dep in deps: ++ depsextras.remove(dep) ++ deps = depsextras ++ for dep in deps: ++ for spec in dep.specs: ++ if spec[0] == '!=': ++ print('Conflicts:\t{} {} {}'.format(dep.key, '==', spec[1])) ++ else: ++ print('Requires:\t{} {} {}'.format(dep.key, spec[0], spec[1])) ++ print('%%description\t{}'.format(extra)) ++ print('{} extra for {} python package'.format(extra, dist.key)) ++ print('%%files\t\textras-{}\n'.format(extra)) ++ if Conflicts: ++ # Should we really add conflicts for extras? ++ # Creating a meta package per extra with recommends on, which has ++ # the requires/conflicts in stead might be a better solution... ++ for dep in dist.requires(extras=dist.extras): ++ name = dep.key ++ for spec in dep.specs: ++ if spec[0] == '!=': ++ if name not in py_deps: ++ py_deps[name] = [] ++ spec = ('==', spec[1]) ++ if spec not in py_deps[name]: ++ py_deps[name].append(spec) ++names = list(py_deps.keys()) ++names.sort() ++for name in names: ++ if py_deps[name]: ++ # Print out versioned provides, requires, recommends, conflicts ++ for spec in py_deps[name]: ++ print('{} {} {}'.format(name, spec[0], spec[1])) ++ else: ++ # Print out unversioned provides, requires, recommends, conflicts ++ print(name) diff --git a/rpm.spec b/rpm.spec index 041fe3b..4a34533 100644 --- a/rpm.spec +++ b/rpm.spec @@ -29,7 +29,7 @@ Summary: The RPM package management system Name: rpm Version: %{rpmver} -Release: %{?snapver:0.%{snapver}.}37%{?dist} +Release: %{?snapver:0.%{snapver}.}38%{?dist} Group: System Environment/Base Url: http://www.rpm.org/ Source0: http://rpm.org/releases/rpm-4.12.x/%{name}-%{srcver}.tar.bz2 @@ -85,6 +85,9 @@ Patch129: rpm-4.13.0-filter-unversioned.patch Patch130: rpm-4.13.0-armv7hl-isa.patch Patch131: rpm-4.13.0-non-ASCII-keys.patch Patch132: rpm-4.13.0-_buildhost-macro.diff +Patch133: rpm-4.13.x-pythondistdeps.patch +Patch134: rpm-4.13.x-pythondistdeps-Makefile.patch +Patch135: rpm-4.13.x-pythondistdeps-fileattr.patch # These are not yet upstream Patch302: rpm-4.7.1-geode-i686.patch @@ -596,6 +599,9 @@ exit 0 %doc doc/librpm/html/* %changelog +* Mon Jun 13 2016 Florian Festi - 4.4.13.0-0.rc1.38 +- Add new Python dependency generator (provides only for now) (#1340885) + * Thu Jun 02 2016 Florian Festi - 4.4.13.0-0.rc1.37 - Add support for _buildhost macro (#1309367)