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