bdist_rpm.py (15531B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\distutils\command\bdist_rpm.py 2 __revision__ = '$Id: bdist_rpm.py 87602 2011-01-01 04:24:26Z richard.tew $' 3 import sys 4 import os 5 import string 6 from distutils.core import Command 7 from distutils.debug import DEBUG 8 from distutils.file_util import write_file 9 from distutils.errors import DistutilsOptionError, DistutilsPlatformError, DistutilsFileError, DistutilsExecError 10 from distutils import log 11 12 class bdist_rpm(Command): 13 description = 'create an RPM distribution' 14 user_options = [('bdist-base=', None, 'base directory for creating built distributions'), 15 ('rpm-base=', None, 'base directory for creating RPMs (defaults to "rpm" under --bdist-base; must be specified for RPM 2)'), 16 ('dist-dir=', 'd', 'directory to put final RPM files in (and .spec files if --spec-only)'), 17 ('python=', None, 'path to Python interpreter to hard-code in the .spec file (default: "python")'), 18 ('fix-python', None, 'hard-code the exact path to the current Python interpreter in the .spec file'), 19 ('spec-only', None, 'only regenerate spec file'), 20 ('source-only', None, 'only generate source RPM'), 21 ('binary-only', None, 'only generate binary RPM'), 22 ('use-bzip2', None, 'use bzip2 instead of gzip to create source distribution'), 23 ('distribution-name=', None, 'name of the (Linux) distribution to which this RPM applies (*not* the name of the module distribution!)'), 24 ('group=', None, 'package classification [default: "Development/Libraries"]'), 25 ('release=', None, 'RPM release number'), 26 ('serial=', None, 'RPM serial number'), 27 ('vendor=', None, 'RPM "vendor" (eg. "Joe Blow <joe@example.com>") [default: maintainer or author from setup script]'), 28 ('packager=', None, 'RPM packager (eg. "Jane Doe <jane@example.net>")[default: vendor]'), 29 ('doc-files=', None, 'list of documentation files (space or comma-separated)'), 30 ('changelog=', None, 'RPM changelog'), 31 ('icon=', None, 'name of icon file'), 32 ('provides=', None, 'capabilities provided by this package'), 33 ('requires=', None, 'capabilities required by this package'), 34 ('conflicts=', None, 'capabilities which conflict with this package'), 35 ('build-requires=', None, 'capabilities required to build this package'), 36 ('obsoletes=', None, 'capabilities made obsolete by this package'), 37 ('no-autoreq', None, 'do not automatically calculate dependencies'), 38 ('keep-temp', 'k', "don't clean up RPM build directory"), 39 ('no-keep-temp', None, 'clean up RPM build directory [default]'), 40 ('use-rpm-opt-flags', None, 'compile with RPM_OPT_FLAGS when building from source RPM'), 41 ('no-rpm-opt-flags', None, 'do not pass any RPM CFLAGS to compiler'), 42 ('rpm3-mode', None, 'RPM 3 compatibility mode (default)'), 43 ('rpm2-mode', None, 'RPM 2 compatibility mode'), 44 ('prep-script=', None, 'Specify a script for the PREP phase of RPM building'), 45 ('build-script=', None, 'Specify a script for the BUILD phase of RPM building'), 46 ('pre-install=', None, 'Specify a script for the pre-INSTALL phase of RPM building'), 47 ('install-script=', None, 'Specify a script for the INSTALL phase of RPM building'), 48 ('post-install=', None, 'Specify a script for the post-INSTALL phase of RPM building'), 49 ('pre-uninstall=', None, 'Specify a script for the pre-UNINSTALL phase of RPM building'), 50 ('post-uninstall=', None, 'Specify a script for the post-UNINSTALL phase of RPM building'), 51 ('clean-script=', None, 'Specify a script for the CLEAN phase of RPM building'), 52 ('verify-script=', None, 'Specify a script for the VERIFY phase of the RPM build'), 53 ('force-arch=', None, 'Force an architecture onto the RPM build process'), 54 ('quiet', 'q', 'Run the INSTALL phase of RPM building in quiet mode')] 55 boolean_options = ['keep-temp', 56 'use-rpm-opt-flags', 57 'rpm3-mode', 58 'no-autoreq', 59 'quiet'] 60 negative_opt = {'no-keep-temp': 'keep-temp', 61 'no-rpm-opt-flags': 'use-rpm-opt-flags', 62 'rpm2-mode': 'rpm3-mode'} 63 64 def initialize_options(self): 65 self.bdist_base = None 66 self.rpm_base = None 67 self.dist_dir = None 68 self.python = None 69 self.fix_python = None 70 self.spec_only = None 71 self.binary_only = None 72 self.source_only = None 73 self.use_bzip2 = None 74 self.distribution_name = None 75 self.group = None 76 self.release = None 77 self.serial = None 78 self.vendor = None 79 self.packager = None 80 self.doc_files = None 81 self.changelog = None 82 self.icon = None 83 self.prep_script = None 84 self.build_script = None 85 self.install_script = None 86 self.clean_script = None 87 self.verify_script = None 88 self.pre_install = None 89 self.post_install = None 90 self.pre_uninstall = None 91 self.post_uninstall = None 92 self.prep = None 93 self.provides = None 94 self.requires = None 95 self.conflicts = None 96 self.build_requires = None 97 self.obsoletes = None 98 self.keep_temp = 0 99 self.use_rpm_opt_flags = 1 100 self.rpm3_mode = 1 101 self.no_autoreq = 0 102 self.force_arch = None 103 self.quiet = 0 104 105 def finalize_options(self): 106 self.set_undefined_options('bdist', ('bdist_base', 'bdist_base')) 107 if self.rpm_base is None: 108 if not self.rpm3_mode: 109 raise DistutilsOptionError, 'you must specify --rpm-base in RPM 2 mode' 110 self.rpm_base = os.path.join(self.bdist_base, 'rpm') 111 if self.python is None: 112 if self.fix_python: 113 self.python = sys.executable 114 else: 115 self.python = 'python' 116 elif self.fix_python: 117 raise DistutilsOptionError, '--python and --fix-python are mutually exclusive options' 118 if os.name != 'posix': 119 raise DistutilsPlatformError, "don't know how to create RPM distributions on platform %s" % os.name 120 if self.binary_only and self.source_only: 121 raise DistutilsOptionError, "cannot supply both '--source-only' and '--binary-only'" 122 if not self.distribution.has_ext_modules(): 123 self.use_rpm_opt_flags = 0 124 self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) 125 self.finalize_package_data() 126 127 def finalize_package_data(self): 128 self.ensure_string('group', 'Development/Libraries') 129 self.ensure_string('vendor', '%s <%s>' % (self.distribution.get_contact(), self.distribution.get_contact_email())) 130 self.ensure_string('packager') 131 self.ensure_string_list('doc_files') 132 if isinstance(self.doc_files, list): 133 for readme in ('README', 'README.txt'): 134 if os.path.exists(readme) and readme not in self.doc_files: 135 self.doc_files.append(readme) 136 137 self.ensure_string('release', '1') 138 self.ensure_string('serial') 139 self.ensure_string('distribution_name') 140 self.ensure_string('changelog') 141 self.changelog = self._format_changelog(self.changelog) 142 self.ensure_filename('icon') 143 self.ensure_filename('prep_script') 144 self.ensure_filename('build_script') 145 self.ensure_filename('install_script') 146 self.ensure_filename('clean_script') 147 self.ensure_filename('verify_script') 148 self.ensure_filename('pre_install') 149 self.ensure_filename('post_install') 150 self.ensure_filename('pre_uninstall') 151 self.ensure_filename('post_uninstall') 152 self.ensure_string_list('provides') 153 self.ensure_string_list('requires') 154 self.ensure_string_list('conflicts') 155 self.ensure_string_list('build_requires') 156 self.ensure_string_list('obsoletes') 157 self.ensure_string('force_arch') 158 159 def run(self): 160 if DEBUG: 161 print 'before _get_package_data():' 162 print 'vendor =', self.vendor 163 print 'packager =', self.packager 164 print 'doc_files =', self.doc_files 165 print 'changelog =', self.changelog 166 if self.spec_only: 167 spec_dir = self.dist_dir 168 self.mkpath(spec_dir) 169 else: 170 rpm_dir = {} 171 for d in ('SOURCES', 'SPECS', 'BUILD', 'RPMS', 'SRPMS'): 172 rpm_dir[d] = os.path.join(self.rpm_base, d) 173 self.mkpath(rpm_dir[d]) 174 175 spec_dir = rpm_dir['SPECS'] 176 spec_path = os.path.join(spec_dir, '%s.spec' % self.distribution.get_name()) 177 self.execute(write_file, (spec_path, self._make_spec_file()), "writing '%s'" % spec_path) 178 if self.spec_only: 179 return 180 saved_dist_files = self.distribution.dist_files[:] 181 sdist = self.reinitialize_command('sdist') 182 if self.use_bzip2: 183 sdist.formats = ['bztar'] 184 else: 185 sdist.formats = ['gztar'] 186 self.run_command('sdist') 187 self.distribution.dist_files = saved_dist_files 188 source = sdist.get_archive_files()[0] 189 source_dir = rpm_dir['SOURCES'] 190 self.copy_file(source, source_dir) 191 if self.icon: 192 if os.path.exists(self.icon): 193 self.copy_file(self.icon, source_dir) 194 else: 195 raise DistutilsFileError, "icon file '%s' does not exist" % self.icon 196 log.info('building RPMs') 197 rpm_cmd = ['rpm'] 198 if os.path.exists('/usr/bin/rpmbuild') or os.path.exists('/bin/rpmbuild'): 199 rpm_cmd = ['rpmbuild'] 200 if self.source_only: 201 rpm_cmd.append('-bs') 202 elif self.binary_only: 203 rpm_cmd.append('-bb') 204 else: 205 rpm_cmd.append('-ba') 206 if self.rpm3_mode: 207 rpm_cmd.extend(['--define', '_topdir %s' % os.path.abspath(self.rpm_base)]) 208 if not self.keep_temp: 209 rpm_cmd.append('--clean') 210 if self.quiet: 211 rpm_cmd.append('--quiet') 212 rpm_cmd.append(spec_path) 213 nvr_string = '%{name}-%{version}-%{release}' 214 src_rpm = nvr_string + '.src.rpm' 215 non_src_rpm = '%{arch}/' + nvr_string + '.%{arch}.rpm' 216 q_cmd = "rpm -q --qf '%s %s\\n' --specfile '%s'" % (src_rpm, non_src_rpm, spec_path) 217 out = os.popen(q_cmd) 218 try: 219 binary_rpms = [] 220 source_rpm = None 221 while 1: 222 line = out.readline() 223 if not line: 224 break 225 l = string.split(string.strip(line)) 226 binary_rpms.append(l[1]) 227 if source_rpm is None: 228 source_rpm = l[0] 229 230 status = out.close() 231 if status: 232 raise DistutilsExecError('Failed to execute: %s' % repr(q_cmd)) 233 finally: 234 out.close() 235 236 self.spawn(rpm_cmd) 237 if not self.dry_run: 238 if not self.binary_only: 239 srpm = os.path.join(rpm_dir['SRPMS'], source_rpm) 240 self.move_file(srpm, self.dist_dir) 241 if not self.source_only: 242 for rpm in binary_rpms: 243 rpm = os.path.join(rpm_dir['RPMS'], rpm) 244 if os.path.exists(rpm): 245 self.move_file(rpm, self.dist_dir) 246 247 def _dist_path(self, path): 248 return os.path.join(self.dist_dir, os.path.basename(path)) 249 250 def _make_spec_file(self): 251 spec_file = ['%define name ' + self.distribution.get_name(), 252 '%define version ' + self.distribution.get_version().replace('-', '_'), 253 '%define unmangled_version ' + self.distribution.get_version(), 254 '%define release ' + self.release.replace('-', '_'), 255 '', 256 'Summary: ' + self.distribution.get_description()] 257 spec_file.extend(['Name: %{name}', 'Version: %{version}', 'Release: %{release}']) 258 if self.use_bzip2: 259 spec_file.append('Source0: %{name}-%{unmangled_version}.tar.bz2') 260 else: 261 spec_file.append('Source0: %{name}-%{unmangled_version}.tar.gz') 262 spec_file.extend(['License: ' + self.distribution.get_license(), 263 'Group: ' + self.group, 264 'BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot', 265 'Prefix: %{_prefix}']) 266 if not self.force_arch: 267 if not self.distribution.has_ext_modules(): 268 spec_file.append('BuildArch: noarch') 269 else: 270 spec_file.append('BuildArch: %s' % self.force_arch) 271 for field in ('Vendor', 'Packager', 'Provides', 'Requires', 'Conflicts', 'Obsoletes'): 272 val = getattr(self, string.lower(field)) 273 if isinstance(val, list): 274 spec_file.append('%s: %s' % (field, string.join(val))) 275 elif val is not None: 276 spec_file.append('%s: %s' % (field, val)) 277 278 if self.distribution.get_url() != 'UNKNOWN': 279 spec_file.append('Url: ' + self.distribution.get_url()) 280 if self.distribution_name: 281 spec_file.append('Distribution: ' + self.distribution_name) 282 if self.build_requires: 283 spec_file.append('BuildRequires: ' + string.join(self.build_requires)) 284 if self.icon: 285 spec_file.append('Icon: ' + os.path.basename(self.icon)) 286 if self.no_autoreq: 287 spec_file.append('AutoReq: 0') 288 spec_file.extend(['', '%description', self.distribution.get_long_description()]) 289 def_setup_call = '%s %s' % (self.python, os.path.basename(sys.argv[0])) 290 def_build = '%s build' % def_setup_call 291 if self.use_rpm_opt_flags: 292 def_build = 'env CFLAGS="$RPM_OPT_FLAGS" ' + def_build 293 install_cmd = '%s install -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES' % def_setup_call 294 script_options = [('prep', 'prep_script', '%setup -n %{name}-%{unmangled_version}'), 295 ('build', 'build_script', def_build), 296 ('install', 'install_script', install_cmd), 297 ('clean', 'clean_script', 'rm -rf $RPM_BUILD_ROOT'), 298 ('verifyscript', 'verify_script', None), 299 ('pre', 'pre_install', None), 300 ('post', 'post_install', None), 301 ('preun', 'pre_uninstall', None), 302 ('postun', 'post_uninstall', None)] 303 for rpm_opt, attr, default in script_options: 304 val = getattr(self, attr) 305 if val or default: 306 spec_file.extend(['', '%' + rpm_opt]) 307 if val: 308 spec_file.extend(string.split(open(val, 'r').read(), '\n')) 309 else: 310 spec_file.append(default) 311 312 spec_file.extend(['', '%files -f INSTALLED_FILES', '%defattr(-,root,root)']) 313 if self.doc_files: 314 spec_file.append('%doc ' + string.join(self.doc_files)) 315 if self.changelog: 316 spec_file.extend(['', '%changelog']) 317 spec_file.extend(self.changelog) 318 return spec_file 319 320 def _format_changelog(self, changelog): 321 if not changelog: 322 return changelog 323 new_changelog = [] 324 for line in string.split(string.strip(changelog), '\n'): 325 line = string.strip(line) 326 if line[0] == '*': 327 new_changelog.extend(['', line]) 328 elif line[0] == '-': 329 new_changelog.append(line) 330 else: 331 new_changelog.append(' ' + line) 332 333 if not new_changelog[0]: 334 del new_changelog[0] 335 return new_changelog