symbian-qemu-0.9.1-12/python-2.6.1/Lib/distutils/command/bdist_rpm.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """distutils.command.bdist_rpm
       
     2 
       
     3 Implements the Distutils 'bdist_rpm' command (create RPM source and binary
       
     4 distributions)."""
       
     5 
       
     6 # This module should be kept compatible with Python 2.1.
       
     7 
       
     8 __revision__ = "$Id: bdist_rpm.py 61000 2008-02-23 17:40:11Z christian.heimes $"
       
     9 
       
    10 import sys, os, string
       
    11 from types import *
       
    12 from distutils.core import Command
       
    13 from distutils.debug import DEBUG
       
    14 from distutils.util import get_platform
       
    15 from distutils.file_util import write_file
       
    16 from distutils.errors import *
       
    17 from distutils.sysconfig import get_python_version
       
    18 from distutils import log
       
    19 
       
    20 class bdist_rpm (Command):
       
    21 
       
    22     description = "create an RPM distribution"
       
    23 
       
    24     user_options = [
       
    25         ('bdist-base=', None,
       
    26          "base directory for creating built distributions"),
       
    27         ('rpm-base=', None,
       
    28          "base directory for creating RPMs (defaults to \"rpm\" under "
       
    29          "--bdist-base; must be specified for RPM 2)"),
       
    30         ('dist-dir=', 'd',
       
    31          "directory to put final RPM files in "
       
    32          "(and .spec files if --spec-only)"),
       
    33         ('python=', None,
       
    34          "path to Python interpreter to hard-code in the .spec file "
       
    35          "(default: \"python\")"),
       
    36         ('fix-python', None,
       
    37          "hard-code the exact path to the current Python interpreter in "
       
    38          "the .spec file"),
       
    39         ('spec-only', None,
       
    40          "only regenerate spec file"),
       
    41         ('source-only', None,
       
    42          "only generate source RPM"),
       
    43         ('binary-only', None,
       
    44          "only generate binary RPM"),
       
    45         ('use-bzip2', None,
       
    46          "use bzip2 instead of gzip to create source distribution"),
       
    47 
       
    48         # More meta-data: too RPM-specific to put in the setup script,
       
    49         # but needs to go in the .spec file -- so we make these options
       
    50         # to "bdist_rpm".  The idea is that packagers would put this
       
    51         # info in setup.cfg, although they are of course free to
       
    52         # supply it on the command line.
       
    53         ('distribution-name=', None,
       
    54          "name of the (Linux) distribution to which this "
       
    55          "RPM applies (*not* the name of the module distribution!)"),
       
    56         ('group=', None,
       
    57          "package classification [default: \"Development/Libraries\"]"),
       
    58         ('release=', None,
       
    59          "RPM release number"),
       
    60         ('serial=', None,
       
    61          "RPM serial number"),
       
    62         ('vendor=', None,
       
    63          "RPM \"vendor\" (eg. \"Joe Blow <joe@example.com>\") "
       
    64          "[default: maintainer or author from setup script]"),
       
    65         ('packager=', None,
       
    66          "RPM packager (eg. \"Jane Doe <jane@example.net>\")"
       
    67          "[default: vendor]"),
       
    68         ('doc-files=', None,
       
    69          "list of documentation files (space or comma-separated)"),
       
    70         ('changelog=', None,
       
    71          "RPM changelog"),
       
    72         ('icon=', None,
       
    73          "name of icon file"),
       
    74         ('provides=', None,
       
    75          "capabilities provided by this package"),
       
    76         ('requires=', None,
       
    77          "capabilities required by this package"),
       
    78         ('conflicts=', None,
       
    79          "capabilities which conflict with this package"),
       
    80         ('build-requires=', None,
       
    81          "capabilities required to build this package"),
       
    82         ('obsoletes=', None,
       
    83          "capabilities made obsolete by this package"),
       
    84         ('no-autoreq', None,
       
    85          "do not automatically calculate dependencies"),
       
    86 
       
    87         # Actions to take when building RPM
       
    88         ('keep-temp', 'k',
       
    89          "don't clean up RPM build directory"),
       
    90         ('no-keep-temp', None,
       
    91          "clean up RPM build directory [default]"),
       
    92         ('use-rpm-opt-flags', None,
       
    93          "compile with RPM_OPT_FLAGS when building from source RPM"),
       
    94         ('no-rpm-opt-flags', None,
       
    95          "do not pass any RPM CFLAGS to compiler"),
       
    96         ('rpm3-mode', None,
       
    97          "RPM 3 compatibility mode (default)"),
       
    98         ('rpm2-mode', None,
       
    99          "RPM 2 compatibility mode"),
       
   100 
       
   101         # Add the hooks necessary for specifying custom scripts
       
   102         ('prep-script=', None,
       
   103          "Specify a script for the PREP phase of RPM building"),
       
   104         ('build-script=', None,
       
   105          "Specify a script for the BUILD phase of RPM building"),
       
   106 
       
   107         ('pre-install=', None,
       
   108          "Specify a script for the pre-INSTALL phase of RPM building"),
       
   109         ('install-script=', None,
       
   110          "Specify a script for the INSTALL phase of RPM building"),
       
   111         ('post-install=', None,
       
   112          "Specify a script for the post-INSTALL phase of RPM building"),
       
   113 
       
   114         ('pre-uninstall=', None,
       
   115          "Specify a script for the pre-UNINSTALL phase of RPM building"),
       
   116         ('post-uninstall=', None,
       
   117          "Specify a script for the post-UNINSTALL phase of RPM building"),
       
   118 
       
   119         ('clean-script=', None,
       
   120          "Specify a script for the CLEAN phase of RPM building"),
       
   121 
       
   122         ('verify-script=', None,
       
   123          "Specify a script for the VERIFY phase of the RPM build"),
       
   124 
       
   125         # Allow a packager to explicitly force an architecture
       
   126         ('force-arch=', None,
       
   127          "Force an architecture onto the RPM build process"),
       
   128        ]
       
   129 
       
   130     boolean_options = ['keep-temp', 'use-rpm-opt-flags', 'rpm3-mode',
       
   131                        'no-autoreq']
       
   132 
       
   133     negative_opt = {'no-keep-temp': 'keep-temp',
       
   134                     'no-rpm-opt-flags': 'use-rpm-opt-flags',
       
   135                     'rpm2-mode': 'rpm3-mode'}
       
   136 
       
   137 
       
   138     def initialize_options (self):
       
   139         self.bdist_base = None
       
   140         self.rpm_base = None
       
   141         self.dist_dir = None
       
   142         self.python = None
       
   143         self.fix_python = None
       
   144         self.spec_only = None
       
   145         self.binary_only = None
       
   146         self.source_only = None
       
   147         self.use_bzip2 = None
       
   148 
       
   149         self.distribution_name = None
       
   150         self.group = None
       
   151         self.release = None
       
   152         self.serial = None
       
   153         self.vendor = None
       
   154         self.packager = None
       
   155         self.doc_files = None
       
   156         self.changelog = None
       
   157         self.icon = None
       
   158 
       
   159         self.prep_script = None
       
   160         self.build_script = None
       
   161         self.install_script = None
       
   162         self.clean_script = None
       
   163         self.verify_script = None
       
   164         self.pre_install = None
       
   165         self.post_install = None
       
   166         self.pre_uninstall = None
       
   167         self.post_uninstall = None
       
   168         self.prep = None
       
   169         self.provides = None
       
   170         self.requires = None
       
   171         self.conflicts = None
       
   172         self.build_requires = None
       
   173         self.obsoletes = None
       
   174 
       
   175         self.keep_temp = 0
       
   176         self.use_rpm_opt_flags = 1
       
   177         self.rpm3_mode = 1
       
   178         self.no_autoreq = 0
       
   179 
       
   180         self.force_arch = None
       
   181 
       
   182     # initialize_options()
       
   183 
       
   184 
       
   185     def finalize_options (self):
       
   186         self.set_undefined_options('bdist', ('bdist_base', 'bdist_base'))
       
   187         if self.rpm_base is None:
       
   188             if not self.rpm3_mode:
       
   189                 raise DistutilsOptionError, \
       
   190                       "you must specify --rpm-base in RPM 2 mode"
       
   191             self.rpm_base = os.path.join(self.bdist_base, "rpm")
       
   192 
       
   193         if self.python is None:
       
   194             if self.fix_python:
       
   195                 self.python = sys.executable
       
   196             else:
       
   197                 self.python = "python"
       
   198         elif self.fix_python:
       
   199             raise DistutilsOptionError, \
       
   200                   "--python and --fix-python are mutually exclusive options"
       
   201 
       
   202         if os.name != 'posix':
       
   203             raise DistutilsPlatformError, \
       
   204                   ("don't know how to create RPM "
       
   205                    "distributions on platform %s" % os.name)
       
   206         if self.binary_only and self.source_only:
       
   207             raise DistutilsOptionError, \
       
   208                   "cannot supply both '--source-only' and '--binary-only'"
       
   209 
       
   210         # don't pass CFLAGS to pure python distributions
       
   211         if not self.distribution.has_ext_modules():
       
   212             self.use_rpm_opt_flags = 0
       
   213 
       
   214         self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
       
   215         self.finalize_package_data()
       
   216 
       
   217     # finalize_options()
       
   218 
       
   219     def finalize_package_data (self):
       
   220         self.ensure_string('group', "Development/Libraries")
       
   221         self.ensure_string('vendor',
       
   222                            "%s <%s>" % (self.distribution.get_contact(),
       
   223                                         self.distribution.get_contact_email()))
       
   224         self.ensure_string('packager')
       
   225         self.ensure_string_list('doc_files')
       
   226         if type(self.doc_files) is ListType:
       
   227             for readme in ('README', 'README.txt'):
       
   228                 if os.path.exists(readme) and readme not in self.doc_files:
       
   229                     self.doc_files.append(readme)
       
   230 
       
   231         self.ensure_string('release', "1")
       
   232         self.ensure_string('serial')   # should it be an int?
       
   233 
       
   234         self.ensure_string('distribution_name')
       
   235 
       
   236         self.ensure_string('changelog')
       
   237           # Format changelog correctly
       
   238         self.changelog = self._format_changelog(self.changelog)
       
   239 
       
   240         self.ensure_filename('icon')
       
   241 
       
   242         self.ensure_filename('prep_script')
       
   243         self.ensure_filename('build_script')
       
   244         self.ensure_filename('install_script')
       
   245         self.ensure_filename('clean_script')
       
   246         self.ensure_filename('verify_script')
       
   247         self.ensure_filename('pre_install')
       
   248         self.ensure_filename('post_install')
       
   249         self.ensure_filename('pre_uninstall')
       
   250         self.ensure_filename('post_uninstall')
       
   251 
       
   252         # XXX don't forget we punted on summaries and descriptions -- they
       
   253         # should be handled here eventually!
       
   254 
       
   255         # Now *this* is some meta-data that belongs in the setup script...
       
   256         self.ensure_string_list('provides')
       
   257         self.ensure_string_list('requires')
       
   258         self.ensure_string_list('conflicts')
       
   259         self.ensure_string_list('build_requires')
       
   260         self.ensure_string_list('obsoletes')
       
   261 
       
   262         self.ensure_string('force_arch')
       
   263     # finalize_package_data ()
       
   264 
       
   265 
       
   266     def run (self):
       
   267 
       
   268         if DEBUG:
       
   269             print "before _get_package_data():"
       
   270             print "vendor =", self.vendor
       
   271             print "packager =", self.packager
       
   272             print "doc_files =", self.doc_files
       
   273             print "changelog =", self.changelog
       
   274 
       
   275         # make directories
       
   276         if self.spec_only:
       
   277             spec_dir = self.dist_dir
       
   278             self.mkpath(spec_dir)
       
   279         else:
       
   280             rpm_dir = {}
       
   281             for d in ('SOURCES', 'SPECS', 'BUILD', 'RPMS', 'SRPMS'):
       
   282                 rpm_dir[d] = os.path.join(self.rpm_base, d)
       
   283                 self.mkpath(rpm_dir[d])
       
   284             spec_dir = rpm_dir['SPECS']
       
   285 
       
   286         # Spec file goes into 'dist_dir' if '--spec-only specified',
       
   287         # build/rpm.<plat> otherwise.
       
   288         spec_path = os.path.join(spec_dir,
       
   289                                  "%s.spec" % self.distribution.get_name())
       
   290         self.execute(write_file,
       
   291                      (spec_path,
       
   292                       self._make_spec_file()),
       
   293                      "writing '%s'" % spec_path)
       
   294 
       
   295         if self.spec_only: # stop if requested
       
   296             return
       
   297 
       
   298         # Make a source distribution and copy to SOURCES directory with
       
   299         # optional icon.
       
   300         saved_dist_files = self.distribution.dist_files[:]
       
   301         sdist = self.reinitialize_command('sdist')
       
   302         if self.use_bzip2:
       
   303             sdist.formats = ['bztar']
       
   304         else:
       
   305             sdist.formats = ['gztar']
       
   306         self.run_command('sdist')
       
   307         self.distribution.dist_files = saved_dist_files
       
   308 
       
   309         source = sdist.get_archive_files()[0]
       
   310         source_dir = rpm_dir['SOURCES']
       
   311         self.copy_file(source, source_dir)
       
   312 
       
   313         if self.icon:
       
   314             if os.path.exists(self.icon):
       
   315                 self.copy_file(self.icon, source_dir)
       
   316             else:
       
   317                 raise DistutilsFileError, \
       
   318                       "icon file '%s' does not exist" % self.icon
       
   319 
       
   320 
       
   321         # build package
       
   322         log.info("building RPMs")
       
   323         rpm_cmd = ['rpm']
       
   324         if os.path.exists('/usr/bin/rpmbuild') or \
       
   325            os.path.exists('/bin/rpmbuild'):
       
   326             rpm_cmd = ['rpmbuild']
       
   327         if self.source_only: # what kind of RPMs?
       
   328             rpm_cmd.append('-bs')
       
   329         elif self.binary_only:
       
   330             rpm_cmd.append('-bb')
       
   331         else:
       
   332             rpm_cmd.append('-ba')
       
   333         if self.rpm3_mode:
       
   334             rpm_cmd.extend(['--define',
       
   335                              '_topdir %s' % os.path.abspath(self.rpm_base)])
       
   336         if not self.keep_temp:
       
   337             rpm_cmd.append('--clean')
       
   338         rpm_cmd.append(spec_path)
       
   339         # Determine the binary rpm names that should be built out of this spec
       
   340         # file
       
   341         # Note that some of these may not be really built (if the file
       
   342         # list is empty)
       
   343         nvr_string = "%{name}-%{version}-%{release}"
       
   344         src_rpm = nvr_string + ".src.rpm"
       
   345         non_src_rpm = "%{arch}/" + nvr_string + ".%{arch}.rpm"
       
   346         q_cmd = r"rpm -q --qf '%s %s\n' --specfile '%s'" % (
       
   347             src_rpm, non_src_rpm, spec_path)
       
   348 
       
   349         out = os.popen(q_cmd)
       
   350         binary_rpms = []
       
   351         source_rpm = None
       
   352         while 1:
       
   353             line = out.readline()
       
   354             if not line:
       
   355                 break
       
   356             l = string.split(string.strip(line))
       
   357             assert(len(l) == 2)
       
   358             binary_rpms.append(l[1])
       
   359             # The source rpm is named after the first entry in the spec file
       
   360             if source_rpm is None:
       
   361                 source_rpm = l[0]
       
   362 
       
   363         status = out.close()
       
   364         if status:
       
   365             raise DistutilsExecError("Failed to execute: %s" % repr(q_cmd))
       
   366 
       
   367         self.spawn(rpm_cmd)
       
   368 
       
   369         if not self.dry_run:
       
   370             if not self.binary_only:
       
   371                 srpm = os.path.join(rpm_dir['SRPMS'], source_rpm)
       
   372                 assert(os.path.exists(srpm))
       
   373                 self.move_file(srpm, self.dist_dir)
       
   374 
       
   375             if not self.source_only:
       
   376                 for rpm in binary_rpms:
       
   377                     rpm = os.path.join(rpm_dir['RPMS'], rpm)
       
   378                     if os.path.exists(rpm):
       
   379                         self.move_file(rpm, self.dist_dir)
       
   380     # run()
       
   381 
       
   382     def _dist_path(self, path):
       
   383         return os.path.join(self.dist_dir, os.path.basename(path))
       
   384 
       
   385     def _make_spec_file(self):
       
   386         """Generate the text of an RPM spec file and return it as a
       
   387         list of strings (one per line).
       
   388         """
       
   389         # definitions and headers
       
   390         spec_file = [
       
   391             '%define name ' + self.distribution.get_name(),
       
   392             '%define version ' + self.distribution.get_version().replace('-','_'),
       
   393             '%define unmangled_version ' + self.distribution.get_version(),
       
   394             '%define release ' + self.release.replace('-','_'),
       
   395             '',
       
   396             'Summary: ' + self.distribution.get_description(),
       
   397             ]
       
   398 
       
   399         # put locale summaries into spec file
       
   400         # XXX not supported for now (hard to put a dictionary
       
   401         # in a config file -- arg!)
       
   402         #for locale in self.summaries.keys():
       
   403         #    spec_file.append('Summary(%s): %s' % (locale,
       
   404         #                                          self.summaries[locale]))
       
   405 
       
   406         spec_file.extend([
       
   407             'Name: %{name}',
       
   408             'Version: %{version}',
       
   409             'Release: %{release}',])
       
   410 
       
   411         # XXX yuck! this filename is available from the "sdist" command,
       
   412         # but only after it has run: and we create the spec file before
       
   413         # running "sdist", in case of --spec-only.
       
   414         if self.use_bzip2:
       
   415             spec_file.append('Source0: %{name}-%{unmangled_version}.tar.bz2')
       
   416         else:
       
   417             spec_file.append('Source0: %{name}-%{unmangled_version}.tar.gz')
       
   418 
       
   419         spec_file.extend([
       
   420             'License: ' + self.distribution.get_license(),
       
   421             'Group: ' + self.group,
       
   422             'BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot',
       
   423             'Prefix: %{_prefix}', ])
       
   424 
       
   425         if not self.force_arch:
       
   426             # noarch if no extension modules
       
   427             if not self.distribution.has_ext_modules():
       
   428                 spec_file.append('BuildArch: noarch')
       
   429         else:
       
   430             spec_file.append( 'BuildArch: %s' % self.force_arch )
       
   431 
       
   432         for field in ('Vendor',
       
   433                       'Packager',
       
   434                       'Provides',
       
   435                       'Requires',
       
   436                       'Conflicts',
       
   437                       'Obsoletes',
       
   438                       ):
       
   439             val = getattr(self, string.lower(field))
       
   440             if type(val) is ListType:
       
   441                 spec_file.append('%s: %s' % (field, string.join(val)))
       
   442             elif val is not None:
       
   443                 spec_file.append('%s: %s' % (field, val))
       
   444 
       
   445 
       
   446         if self.distribution.get_url() != 'UNKNOWN':
       
   447             spec_file.append('Url: ' + self.distribution.get_url())
       
   448 
       
   449         if self.distribution_name:
       
   450             spec_file.append('Distribution: ' + self.distribution_name)
       
   451 
       
   452         if self.build_requires:
       
   453             spec_file.append('BuildRequires: ' +
       
   454                              string.join(self.build_requires))
       
   455 
       
   456         if self.icon:
       
   457             spec_file.append('Icon: ' + os.path.basename(self.icon))
       
   458 
       
   459         if self.no_autoreq:
       
   460             spec_file.append('AutoReq: 0')
       
   461 
       
   462         spec_file.extend([
       
   463             '',
       
   464             '%description',
       
   465             self.distribution.get_long_description()
       
   466             ])
       
   467 
       
   468         # put locale descriptions into spec file
       
   469         # XXX again, suppressed because config file syntax doesn't
       
   470         # easily support this ;-(
       
   471         #for locale in self.descriptions.keys():
       
   472         #    spec_file.extend([
       
   473         #        '',
       
   474         #        '%description -l ' + locale,
       
   475         #        self.descriptions[locale],
       
   476         #        ])
       
   477 
       
   478         # rpm scripts
       
   479         # figure out default build script
       
   480         def_setup_call = "%s %s" % (self.python,os.path.basename(sys.argv[0]))
       
   481         def_build = "%s build" % def_setup_call
       
   482         if self.use_rpm_opt_flags:
       
   483             def_build = 'env CFLAGS="$RPM_OPT_FLAGS" ' + def_build
       
   484 
       
   485         # insert contents of files
       
   486 
       
   487         # XXX this is kind of misleading: user-supplied options are files
       
   488         # that we open and interpolate into the spec file, but the defaults
       
   489         # are just text that we drop in as-is.  Hmmm.
       
   490 
       
   491         script_options = [
       
   492             ('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"),
       
   493             ('build', 'build_script', def_build),
       
   494             ('install', 'install_script',
       
   495              ("%s install "
       
   496               "--root=$RPM_BUILD_ROOT "
       
   497               "--record=INSTALLED_FILES") % def_setup_call),
       
   498             ('clean', 'clean_script', "rm -rf $RPM_BUILD_ROOT"),
       
   499             ('verifyscript', 'verify_script', None),
       
   500             ('pre', 'pre_install', None),
       
   501             ('post', 'post_install', None),
       
   502             ('preun', 'pre_uninstall', None),
       
   503             ('postun', 'post_uninstall', None),
       
   504         ]
       
   505 
       
   506         for (rpm_opt, attr, default) in script_options:
       
   507             # Insert contents of file referred to, if no file is referred to
       
   508             # use 'default' as contents of script
       
   509             val = getattr(self, attr)
       
   510             if val or default:
       
   511                 spec_file.extend([
       
   512                     '',
       
   513                     '%' + rpm_opt,])
       
   514                 if val:
       
   515                     spec_file.extend(string.split(open(val, 'r').read(), '\n'))
       
   516                 else:
       
   517                     spec_file.append(default)
       
   518 
       
   519 
       
   520         # files section
       
   521         spec_file.extend([
       
   522             '',
       
   523             '%files -f INSTALLED_FILES',
       
   524             '%defattr(-,root,root)',
       
   525             ])
       
   526 
       
   527         if self.doc_files:
       
   528             spec_file.append('%doc ' + string.join(self.doc_files))
       
   529 
       
   530         if self.changelog:
       
   531             spec_file.extend([
       
   532                 '',
       
   533                 '%changelog',])
       
   534             spec_file.extend(self.changelog)
       
   535 
       
   536         return spec_file
       
   537 
       
   538     # _make_spec_file ()
       
   539 
       
   540     def _format_changelog(self, changelog):
       
   541         """Format the changelog correctly and convert it to a list of strings
       
   542         """
       
   543         if not changelog:
       
   544             return changelog
       
   545         new_changelog = []
       
   546         for line in string.split(string.strip(changelog), '\n'):
       
   547             line = string.strip(line)
       
   548             if line[0] == '*':
       
   549                 new_changelog.extend(['', line])
       
   550             elif line[0] == '-':
       
   551                 new_changelog.append(line)
       
   552             else:
       
   553                 new_changelog.append('  ' + line)
       
   554 
       
   555         # strip trailing newline inserted by first changelog entry
       
   556         if not new_changelog[0]:
       
   557             del new_changelog[0]
       
   558 
       
   559         return new_changelog
       
   560 
       
   561     # _format_changelog()
       
   562 
       
   563 # class bdist_rpm