From 2b1d8168f5396113126f10bb6348f94c12db5bf2 Mon Sep 17 00:00:00 2001 From: Marcin Krol Date: Fri, 1 Nov 2019 12:33:03 +0100 Subject: [PATCH] - backported pythonegg deps resolver --- rpm-pythondeps.patch | 327 +++++++++++++++++++++++++++++++++++++++++++ rpm.spec | 5 +- 2 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 rpm-pythondeps.patch diff --git a/rpm-pythondeps.patch b/rpm-pythondeps.patch new file mode 100644 index 0000000..9772b6e --- /dev/null +++ b/rpm-pythondeps.patch @@ -0,0 +1,327 @@ +diff -urN rpm-4.5.orig/macros.in rpm-4.5/macros.in +--- rpm-4.5.orig/macros.in 2019-06-01 18:55:39.553000000 +0200 ++++ rpm-4.5/macros.in 2019-11-01 12:11:16.312000000 +0100 +@@ -1404,25 +1404,46 @@ + # + # Path to scripts to autogenerate python package dependencies, + # +-# Note: Used iff _use_internal_dependency_generator is non-zero. The ++# Note: Used if _use_internal_dependency_generator is non-zero. The + # helpers are also used by %{_rpmhome}/rpmdeps {--provides|--requires}. +-%__python_provides /usr/bin/env PYVER=%py_ver %{_rpmhome}/pythondeps.sh --provides +-%__python_requires /usr/bin/env PYVER=%py_ver %{_rpmhome}/pythondeps.sh --requires +- +-# Useful macros for building *.rpm python packages (for python > 1.6). ++%__python_provides %{_rpmhome}/pythoneggs.py --provides ++%__python_requires %{_rpmhome}/pythoneggs.py --requires + # +-%python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)") +-%python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()") +-%python_version %(%{__python} -c "import sys; print(sys.version[0:3])") ++%python_sitearch %(%{__python} -c "import os; from distutils.sysconfig import get_python_lib; lib=get_python_lib(1); print os.path.islink(lib) and os.path.abspath(os.path.join(os.path.dirname(lib),os.readlink(lib))) or lib") ++%python_sitelib %(%{__python} -c "import os; from distutils.sysconfig import get_python_lib; lib=get_python_lib(); print os.path.islink(lib) and os.path.abspath(os.path.join(os.path.dirname(lib),os.readlink(lib))) or lib") ++%python_version %(%{__python} -c "import sys; print(sys.version[0:3])") ++ ++# python main version ++%py_ver %(%{__python} -c "import sys; v=sys.version_info[:2]; print '%%d.%%d'%%v" 2>/dev/null || echo PYTHON-NOT-FOUND) ++%py_prefix %(%{__python} -c "import sys; print sys.prefix" 2>/dev/null || echo PYTHON-NOT-FOUND) ++%py_platlibdir %(%{__python} -c 'import distutils.sysconfig; print distutils.sysconfig.get_python_lib(standard_lib=1,plat_specific=1)' 2>/dev/null || echo PYTHON-LIBDIR-NOT-FOUND) ++%py_purelibdir %(%{__python} -c 'import distutils.sysconfig; print distutils.sysconfig.get_python_lib(standard_lib=1,plat_specific=0)' 2>/dev/null || echo PYTHON-LIBDIR-NOT-FOUND) ++# backward compatibility ++%py_libdir %py_purelibdir ++ ++%py_platsitedir %(%{__python} -c 'import distutils.sysconfig; print distutils.sysconfig.get_python_lib(plat_specific=1)' 2>/dev/null || echo PYTHON-LIBDIR-NOT-FOUND) ++%py_puresitedir %(%{__python} -c 'import distutils.sysconfig; print distutils.sysconfig.get_python_lib()' 2>/dev/null || echo PYTHON-LIBDIR-NOT-FOUND) ++%py_sitedir %py_puresitedir ++ ++%py_dyndir %{py_platlibdir}/lib-dynload ++ ++%py_incdir %(%{__python} -c 'import distutils.sysconfig; print distutils.sysconfig.get_python_inc()' 2>/dev/null || echo PYTHON-INCLUDEDIR-NOT-FOUND) + + %py_compile(O) \ +-find %1 -name '*.pyc' -name '*.pyo' -exec rm -f {} \\; \ +-%{__python} %{?O:-O} -c "import sys, os, compileall; br='%{buildroot}'; compileall.compile_dir(sys.argv[1], ddir=br and (sys.argv[1][len(os.path.abspath(br)):]+'/') or None)" %1 \ ++find %1 -name '*.pyc' -exec rm -f {} \\; \ ++%{__python} -c "import sys, os, compileall; br='%{buildroot}'; compileall.compile_dir(sys.argv[1], ddir=br and (sys.argv[1][len(os.path.abspath(br)):]+'/') or None)" %1 \ ++%{-O: \ ++find %1 -name '*.pyo' -exec rm -f {} \\; \ ++%{__python} -O -c "import sys, os, compileall; br='%{buildroot}'; compileall.compile_dir(sys.argv[1], ddir=br and (sys.argv[1][len(os.path.abspath(br)):]+'/') or None)" %1 \ ++} ++ ++# pure python modules compilation ++%py_comp %{__python} -c "import compileall; import sys; compileall.compile_dir(sys.argv[1], ddir=sys.argv[1][len('%{buildroot}'):])" ++ ++%py_ocomp %{__python} -O -c "import compileall; import sys; compileall.compile_dir(sys.argv[1], ddir=sys.argv[1][len('%{buildroot}'):])" + + %py_requires(d) \ +-%define maxver %(%{__python} -c "import sys; a,b=sys.version_info[:2]; print '%%d.%%d'%%(a,b+1)" 2>/dev/null || echo PYTHON-NOT-FOUND) \ +-BuildRequires: python %{-d:python-devel} \ +-PreReq: python >= %{python_version}, python < %{maxver} ++BuildRequires: %{__python} %{-d:python-devel} + + #------------------------------------------------------------------------ + # php(...) configuration. +diff -urN rpm-4.5.orig/scripts/Makefile.am rpm-4.5/scripts/Makefile.am +--- rpm-4.5.orig/scripts/Makefile.am 2019-06-01 18:55:39.553000000 +0200 ++++ rpm-4.5/scripts/Makefile.am 2019-11-01 12:03:59.288000000 +0100 +@@ -12,7 +12,8 @@ + find-requires.perl freshen.sh gendiff getpo.sh http.req \ + check-java-closure.sh java.prov.sh java.req.sh \ + javadeps.sh libtooldeps.sh pkgconfigdeps.sh \ +- perldeps.pl perl.prov perl.req pythondeps.sh mimetypedeps.sh \ ++ perldeps.pl perl.prov perl.req pythondeps.sh pythoneggs.py \ ++ mimetypedeps.sh \ + php.prov php.req rpm2cpio \ + rpmdb_loadcvt rpmdiff rpmdiff.cgi \ + rpm.daily rpm.log rpm.xinetd \ +@@ -39,7 +40,8 @@ + find-provides.perl \ + find-requires.perl getpo.sh http.req \ + javadeps.sh libtooldeps.sh pkgconfigdeps.sh \ +- perldeps.pl perl.prov perl.req pythondeps.sh mimetypedeps.sh \ ++ perldeps.pl perl.prov perl.req pythondeps.sh pythoneggs.py \ ++ mimetypedeps.sh \ + php.prov php.req \ + rpmdb_loadcvt \ + rpm.daily rpm.log rpm.xinetd \ +diff -urN rpm-4.5.orig/scripts/pythoneggs.py rpm-4.5/scripts/pythoneggs.py +--- rpm-4.5.orig/scripts/pythoneggs.py 1970-01-01 01:00:00.000000000 +0100 ++++ rpm-4.5/scripts/pythoneggs.py 2019-03-09 02:30:08.000000000 +0100 +@@ -0,0 +1,237 @@ ++#!/usr/bin/env python ++# -*- coding: utf-8 -*- ++# ++# Copyright 2010 Per Øyvind Karlsen ++# ++# This program is free software. It may be redistributed and/or modified under ++# the terms of the LGPL version 2.1 (or later). ++# ++# RPM5 python (egg) dependency generator. ++# ++ ++from getopt import getopt ++from os.path import basename, dirname, isdir, sep, splitext ++from sys import argv, stdin, version ++from pkg_resources import Distribution, FileMetadata, PathMetadata ++from distutils.sysconfig import get_python_lib ++from subprocess import Popen, PIPE, STDOUT ++import os ++import platform ++import re ++ ++opts, args = getopt(argv[1:], 'hPRSCOEb:', ++ ['help', 'provides', 'requires', 'suggests', 'conflicts', 'obsoletes', 'extras','buildroot=']) ++ ++Provides = False ++Requires = False ++Suggests = False ++Conflicts = False ++Obsoletes = False ++Extras = False ++buildroot = None ++ ++def make_pldver(raw): ++ if re.match(r'^[0-9\.]+$', raw) == None: ++ pldver = re.sub(r'([\d\.]+)(.+)', r'\1-0.\2', raw) ++ else: ++ pldver = raw ++ return pldver ++ ++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 '-S, --suggests\tPrint Suggests' ++ print '-C, --conflicts\tPrint Conflicts' ++ print '-O, --obsoletes\tPrint Obsoletes (unused)' ++ print '-E, --extras\tPrint Extras ' ++ print '-b, --buildroot\tBuildroot for package ' ++ exit(1) ++ elif o in ('-P', '--provides'): ++ Provides = True ++ elif o in ('-R', '--requires'): ++ Requires = True ++ elif o in ('-S', '--suggests'): ++ Suggests = True ++ elif o in ('-C', '--conflicts'): ++ Conflicts = True ++ elif o in ('-O', '--obsoletes'): ++ Obsoletes = True ++ elif o in ('-E', '--extras'): ++ Extras = True ++ elif o in ('-b', '--buildroot'): ++ buildroot = a ++ ++def is_exe(fpath): ++ return os.path.isfile(fpath) and os.access(fpath, os.X_OK) ++ ++typelib_check = False ++ ++if is_exe("/usr/lib/rpm/gi-find-deps.sh") and is_exe("/usr/bin/g-ir-dep-tool"): ++ if not buildroot: ++ pass ++ else: ++ typelib_check = 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 not name 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 not spec in py_deps[name]: ++ py_deps[name].append(spec) ++ # Pipe files to find typelib requires ++ if typelib_check: ++ p = Popen(['/usr/lib/rpm/gi-find-deps.sh', '-R',str(buildroot)], stdout=PIPE, stdin=PIPE, stderr=STDOUT) ++ (stdoutdata, stderrdata) = p.communicate(input=str(f)+"\n") ++ ++ if stdoutdata and stdoutdata: ++ py_deps[stdoutdata.strip()]= "" ++ ++ # XXX: hack to workaround RPM internal dependency generator not passing directories ++ dlower = dirname(lower) ++ if dlower.endswith('.egg') or \ ++ dlower.endswith('.egg-info') or \ ++ dlower.endswith('.egg-link'): ++ lower = dlower ++ f = dirname(f) ++ # Determine provide, requires, conflicts & suggests based on egg metadata ++ if lower.endswith('.egg') or \ ++ lower.endswith('.egg-info') or \ ++ lower.endswith('.egg-link'): ++ 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: ++ # If egg metadata says package name is python, we provide python(abi) ++ if dist.key == 'python': ++ name = 'python(abi)' ++ if not name in py_deps: ++ py_deps[name] = [] ++ py_deps[name].append(('==', dist.py_version)) ++ if dist.py_version .split(".")[0] == '3': ++ name = 'python3egg(%s)' % dist.key ++ else: ++ name = 'pythonegg(%s)' % dist.key ++ if not name in py_deps: ++ py_deps[name] = [] ++ if dist.version: ++ spec = ('==', make_pldver(dist.version)) ++ if not spec in py_deps[name]: ++ py_deps[name].append(spec) ++ if Requires or (Suggests and dist.extras): ++ name = 'python(abi)' ++ # If egg 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 not name in py_deps: ++ py_deps[name] = [] ++ spec = ('==', dist.py_version) ++ if not spec in py_deps[name]: ++ py_deps[name].append(spec) ++ # fake python version for dist.requires(), so deps like ++ # [:python_version < '3'] ++ # enum34 ++ # will be handled correctly ++ old_python_version = platform.python_version ++ def new_python_version(): ++ return dist.py_version ++ platform.python_version = new_python_version ++ deps = dist.requires() ++ if Suggests: ++ depsextras = dist.requires(extras=dist.extras) ++ if not Requires: ++ for dep in reversed(depsextras): ++ if dep in deps: ++ depsextras.remove(dep) ++ deps = depsextras ++ platform.python_version = old_python_version ++ # add requires/suggests based on egg metadata ++ for dep in deps: ++ if dist.py_version .split(".")[0] == '3': ++ name = 'python3egg(%s)' % dep.key ++ else: ++ name = 'pythonegg(%s)' % dep.key ++ for spec in dep.specs: ++ if spec[0] != '!=': ++ if not name in py_deps: ++ py_deps[name] = [] ++ plddep = (spec[0], make_pldver(spec[1])) ++ if not plddep in py_deps[name]: ++ py_deps[name].append(plddep) ++ if not dep.specs: ++ py_deps[name] = [] ++ # Unused, for automatic sub-package generation based on 'extras' from egg metadata ++ # TODO: implement in rpm later, or...? ++ if Extras: ++ deps = dist.requires() ++ extras = dist.extras ++ print extras ++ for extra in extras: ++ print '%%package\textras-%s' % extra ++ print 'Summary:\t%s extra for %s python egg' % (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%s %s %s' % (dep.key, '==', spec[1]) ++ else: ++ print 'Requires:\t%s %s %s' % (dep.key, spec[0], spec[1]) ++ print '%%description\t%s' % extra ++ print '%s extra for %s python egg' % (extra, dist.key) ++ print '%%files\t\textras-%s\n' % extra ++ if Conflicts: ++ # Should we really add conflicts for extras? ++ # Creating a meta package per extra with suggests 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 not name in py_deps: ++ py_deps[name] = [] ++ spec = ('==', spec[1]) ++ if not spec in py_deps[name]: ++ py_deps[name].append(spec) ++names = py_deps.keys() ++names.sort() ++for name in names: ++ if py_deps[name]: ++ # Print out versioned provides, requires, suggests, conflicts ++ for spec in py_deps[name]: ++ print '%s %s %s' % (name, spec[0], spec[1]) ++ else: ++ # Print out unversioned provides, requires, suggests, conflicts ++ print name diff --git a/rpm.spec b/rpm.spec index 66c105e..6a36f27 100644 --- a/rpm.spec +++ b/rpm.spec @@ -42,7 +42,7 @@ Summary(ru.UTF-8): Менеджер пакетов от RPM Summary(uk.UTF-8): Менеджер пакетів від RPM Name: rpm Version: 4.5 -Release: 88 +Release: 89 License: LGPL Group: Base Source0: %{name}-%{version}.tar.gz @@ -179,6 +179,7 @@ Patch116: %{name}-trigger-flags-int-type.patch Patch117: %{name}-rpm2cpio-xz.patch Patch118: %{name}-noarch-subpackages.patch Patch119: %{name}-div0.patch +Patch120: %{name}-pythondeps.patch URL: http://rpm5.org/ BuildRequires: autoconf >= 2.57 BuildRequires: automake >= 1.4 @@ -825,6 +826,7 @@ install %{SOURCE13} scripts/perl.prov %patch117 -p1 %patch118 -p1 %patch119 -p1 +%patch120 -p1 mv -f po/{sr,sr@Latn}.po rm -rf sqlite zlib popt @@ -1458,6 +1460,7 @@ find %{_rpmlibdir} -name '*-linux' -type l | xargs rm -f %defattr(644,root,root,755) %{_rpmlibdir}/macros.python %attr(755,root,root) %{_rpmlibdir}/pythondeps.sh +%attr(755,root,root) %{_rpmlibdir}/pythoneggs.py %files php-pearprov %defattr(644,root,root,755) -- 2.46.0