.. CDDL HEADER START .. The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] .. CDDL HEADER END .. Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. Chapter 8 --------- Modifying Package Manifests Programmatically ............................................ This chapter explains how package manifests can be machine edited to permit the automated annotation and checking of package manifests. *Chapter 4* covers the basics for how to publish packages. These techniques are all that is necessary to publish a package, but when publishing a large package, a large number of packages, or publishing packages over a period of time, there can be aspects which involve a significant time commitment for doing repetitive tasks. For example, one rule that's used when publishing Oracle Solaris is that all kernel modules should be tagged as requiring a reboot. One option would be to impose this constraint through human examination and intervention, but that would be costly and likely error prone. A second option would be to write a script or program that would handle tagging these actions. The difficulty here is that to be sure the program tagged actions correctly, it would need to parse the actions. This can certainly be done, but it duplicates a lot of functionality already in the IPS framework. The third, and best, option is to use |pkgmogrify|, provided by IPS, to transform the package manifests in repeatable ways. There are two types of rules |pkgmogrify| understands, transform and include. Transform rules are used to modify actions. Include rules cause other files to be processed. Transform Rules ~~~~~~~~~~~~~~~ When publishing Oracle Solaris, we made the assumption that all files delivering in a subdirectory named "``kernel``" should be treated as kernel modules. This is the rule used to do the tagging:: default reboot-needed true> .. * The rule is enclosed with ‘``<``’ and ‘``>``’. The portion of the rule to the left of the ‘``->``’ is the selection section or matching section. The portion to the right of the ‘``->``’ is the execution section of the operation. * ‘``transform``’ is the type of the rule * ‘``file``’ means this rule is for ``file`` actions * ‘``path=.*kernel/.+``’ means that only file actions with a path attribute that matches the regular expression ‘``.*kernel/.+``’ are transformed * ‘``default``’ means that what follows should be added to a matching action unless a value for the attribute has already been set * ‘``reboot-needed``’ is the attribute being set * ‘``true``’ is the value of the attribute The selection or matching section of a transform rule can restrict by action type and by action attribute values. The |pkgmogrify| man page goes into detail about how these matching rules work, but the typical uses are for selecting actions which deliver to certain areas of the file system. .. raw:: pdf PageBreak For example, a rule that began like this .. parsed-literal:: *[operation]*> could be used to ensure that ``usr/bin`` and everything delivered inside of it defaulted to the correct user or group. There is a long list of operations which |pkgmogrify| can perform, detailed in the man page, which enable a package developer to programmatically add, remove, set, and edit actions' attributes as well as add and remove entire actions. Include Rules ~~~~~~~~~~~~~ Include rules enable transforms to be spread across multiple files and subsets reused by different manifests. Suppose a developer needs to deliver two packages: A and B. Both packages should have their ``source-url`` set to the same url, but only package B should have its files in ``/etc`` set to be ``group=sys``. In the manifest for package A, an include rule which pulls in the file with the ``source-url`` transform should be added. In package B, an include rule which pulls in the file containing the file ``group`` setting transform should be added. Finally, an include rule which pulls in the file with the ``source-url`` transform should be added to either package B or the file with the transform that sets the group. Transform Order ~~~~~~~~~~~~~~~ Transforms are applied in the order in which they are encountered in a file. The ordering can be used to simplify the matching portions of transforms. Suppose all files delivered in ``/foo`` should have a default group of ``sys``, except those delivered in ``/foo/bar``, which should have a default group of ``bin``. It's certainly possible to write a complex regular expression which matches all paths that begin with ``/foo``, except those that begin with ``/foo/bar``. Using the ordering of transforms makes it much simpler. When ordering default transforms, always go from most specific to most general. Otherwise the latter rules will never be used. In this case, the two rules would look like this:: default group bin> default group sys> Using transforms to add an action using the matching described above would be difficult since the package developer would need to find a pattern which matched each package delivered once and only once. |pkgmogrify| creates synthetic actions to help with this issue. As |pkgmogrify| processes manifests, for each manifest that sets the ``pkg.fmri`` attribute, a synthetic *pkg action* is created by |pkgmogrify|. The package developer can match against the ``pkg`` action as if it was actually in the manifest. For example, suppose a package developer wanted to add to every package an action containing the website (foo.com) where the source code for the delivered software can be found. The following transform accomplishes that:: emit set info.source-url=http://foo.com> .. raw:: pdf PageBreak Packaged Transforms ~~~~~~~~~~~~~~~~~~~ As a convenience to developers, a set of the transforms that were used when packaging Oracle Solaris itself are available in ``/usr/share/pkg/transforms``. At the time of writing, these are: **developer** Sets ``facet.devel`` on ``*.h`` header files delivered to ``/usr/.*/include``, archive and lint libraries, ``pkg-config(1)`` data files, and ``autoconf(1)`` macros. **documentation** Sets a variety of ``facet.doc.*`` facets on documentation files. **locale** Sets a variety of ``facet.locale.*`` facets on files which are locale-specific. **smf-manifests** Adds a ``restart_fmri`` actuator pointing to the ``svc:/system/manifest-import:default`` on any packaged SMF manifests so that the system will import that manifest after the package is installed.