GConf Scriptlets (draft)

Existing Guideline
Packaging/ScriptletSnippets

Problems

 * The current GConf scriptlets use more resources than necessary. Everytime a package with a GConf schema is upgraded, GConftool-2 has to be run twice.  Once to parse and remove the current xml schema and a second time to parse and install the new schema.  In the majority of package upgrades, the GConf schema hasn't changed from the previous version which makes both of these steps unnecessary.


 * The GConf scriptlets are coded into many spec files. If changes are made to GConf, each of the packages has to be recoded.  This will be a factor in the near future as there are plans to change GConf to store registered schemas in %{_datadir} for FHS compliance.  Note that when this happens, we'll need to modify the macros to look in both %{_sysconfdir}/gconf/schemas/ and %{_datadir}/gconf/schemas for the schema files to uninstall.

These are the scriptlets we currently code into every spec file: Requires(pre): GConf2 Requires(post): GConf2 Requires(preun): GConf2

%install rm -rf $RPM_BUILD_ROOT export GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1 make install DESTDIR=$RPM_BUILD_ROOT

%pre if [ "$1" -gt 1 ] ; then export GCONF_CONFIG_SOURCE= gconftool-2 --makefile-uninstall-rule \ %{_sysconfdir}/gconf/schemas/[NAME] .schemas >/dev/null || : fi

%post export GCONF_CONFIG_SOURCE= gconftool-2 --makefile-install-rule \ %{_sysconfdir}/gconf/schemas/[NAME] .schemas > /dev/null || :

%preun if [ "$1" -eq 0 ] ; then export GCONF_CONFIG_SOURCE= gconftool-2 --makefile-uninstall-rule \ %{_sysconfdir}/gconf/schemas/[NAME] .schemas > /dev/null || : fi

The %pre, %post, and %preun sections would change under this proposal.

The proposal modifies the current Guidelines by replacing everything from "Here's the second part" on:

Proposal
Here's the second part: Requires(pre): GConf2 Requires(post): GConf2 Requires(preun): GConf2 ... %pre %gconf_schema_prepare schema1 schema2 %gconf_schema_obsolete schema3 In this section we uninstall old schemas during upgrade using one of two macros.

is used for any current GConf schemas. It takes care of uninstalling previous versions of schemas that this package currently installs. It takes a space separated list of schema names without path or suffix that the package installs. Note that behind the scenes, this macro works with the  scriptlet to only process GConf schemas if changes have occurred.

is used for schemas that this package previously provided but no longer does. It will deregister the old schema if it is present on the system. Nothing will happen if the old schema is not present. This macro takes a space separated list of schemas to uninstall. One example of using this might be if the package changed names. If the old schema was named  and the new schema is named you'd use:

%gconf_schema_prepare foobar %gconf_schema_obsolete foo

The next section does the processing of the newly installed schemas: %post %gconf_schema_upgrade schema1 schema2

takes a space separated list of schemas that the package currently installs just like. Behind the scenes, it does the actual work of registering the new version of the schema and deregistering the old version.

The last section is for unregistering schemas when a package is removed: %preun %gconf_schema_remove schema1 schema2 When a package is upgraded rpm invokes the  scriptlet to register and deregister the schemas. When a package is uninstalled, the scriptlet is used. takes the list of schemas that this package currently provides and removes them for us.

Rebuilds for changes to macros
When macros change, packages that make use of them have to be rebuilt to pick up the changes. This repoquery command can be used to find the schema including packages to rebuild: repoquery --whatprovides "/etc/gconf/schemas/*" |sort |uniq |wc -l

Behind the scenes
These are the changes that need to be implemented to support the new Guidelines.

OpenSuSE has solved the problem of code changing in the rpm spec files by making macros for GConf schema registration. They have solved the inefficiency problem by comparing the old and new schemas and only running gconftool-2 if the schemas differ. We've taken the same basic approach but tried to keep the macros simpler.

Disclaimer
Adapted from macro.gconf2.


 * License from author is LGPL v2.1+ from email conversation (with spstarr):

"I did not assign any special license to macros.gconf2.

I think that if not declared otherwise, rpm source files have the same license as the package itself. In case of gconf2 it is: GPL v2 or later; LGPL v2.1 or later

So feel free to consider it as LGPL v2.1 or later.

I think, that LGPL should allow to use them in proprietary GNOME packages, exactly as gconf2 license allows.

Maybe it would be good to mention the license explicitly."

- Stanislav Brabec

macros.gconf2

 * 1) RPM macros for gconf applications.
 * 2) (c) 2006-2007 SUSE LINUX
 * 3) Author: Stanislav Brabec 
 * 4) (c) 2009 Red Hat, Inc
 * 5) Author: Toshio Kuratomi 
 * 6) License: LGPLv2+
 * 7) Usage:
 * 8) Preamble:
 * 9) Requires(pre): GConf2
 * 10) Requires(preun): GConf2
 * 11) Requires(post): GConf2
 * 12) schemas names are without path and suffix
 * 13) %pre
 * 14) %gconf_schema_obsolete schema1
 * 15) %gconf_schema_prepare schema2 schema3
 * 16) %preun
 * 17) %gconf_schema_remove schema2 schema3
 * 18) %post
 * 19) %gconf_schema_upgrade schema2 schema3
 * 20) %files
 * 21) %{_sysconfdir}/gconf/schemas/schema2.schemas
 * 22) %{_sysconfdir}/gconf/schemas/schema3.schemas
 * 1) %gconf_schema_prepare schema2 schema3
 * 2) %preun
 * 3) %gconf_schema_remove schema2 schema3
 * 4) %post
 * 5) %gconf_schema_upgrade schema2 schema3
 * 6) %files
 * 7) %{_sysconfdir}/gconf/schemas/schema2.schemas
 * 8) %{_sysconfdir}/gconf/schemas/schema3.schemas
 * 1) %files
 * 2) %{_sysconfdir}/gconf/schemas/schema2.schemas
 * 3) %{_sysconfdir}/gconf/schemas/schema3.schemas

%gconf_schema_prepare \ if [ "$1" -gt 1 ] ; then \ rm -rf %{_localstatedir}/lib/rpm-state/gconf/* \ for schema in %{*} ; do \ if test -f %{_sysconfdir}/gconf/schemas/"$schema".schemas ; then \ cp -p %{_sysconfdir}/gconf/schemas/"$schema".schemas %{_localstatedir}/lib/rpm-state/gconf/ || : \ fi \ done \ fi \ %{nil}
 * 1) Copy schemas from old package for later uninstall on upgrade

%_do_gconf_schema_remove \ if test -f %{_sysconfdir}/gconf/schemas/"$schema".schemas ; then \ export GCONF_CONFIG_SOURCE=`gconftool-2 --get-default-source` \ gconftool-2 --makefile-uninstall-rule %{_sysconfdir}/gconf/schemas/"$schema".schemas > /dev/null || : \ fi \ %{nil}
 * 1) Macro to remove schemas.  Not meant to be used publically

%gconf_schema_obsolete \ for schema in %{*} ; do \ %_do_gconf_schema_remove \ done \ %{nil}
 * 1) Remove schemas unconditionally

%gconf_schema_remove \ if [ "$1" -eq 0 ] ; then \ for schema in %{*} ; do \ %_do_gconf_schema_remove \ done \ fi \ %{nil}
 * 1) Remove schemas on package removal (not upgrade)

%gconf_schema_upgrade \ for schema in %{*} ; do \ if test -f %{_localstatedir}/lib/rpm-state/gconf/"$schema".schemas ; then \ cmp --quiet %{_sysconfdir}/gconf/schemas/"$schema".schemas %{_localstatedir}/lib/rpm-state/gconf/"$schema".schemas \ if test $? != 0; then\ %_do_gconf_schema_remove \ export GCONF_CONFIG_SOURCE=`gconftool-2 --get-default-source` \ gconftool-2 --makefile-install-rule %{_sysconfdir}/gconf/schemas/"$schema".schemas > /dev/null || : \ fi \ rm -f %{_localstatedir}/lib/rpm-state/gconf/"$schema".schemas \ else \ export GCONF_CONFIG_SOURCE=`gconftool-2 --get-default-source` \ gconftool-2 --makefile-install-rule %{_sysconfdir}/gconf/schemas/"$schema".schemas > /dev/null || : \ fi \ done \ %{nil}

Open Questions

 * Need to find a package to own /var/lib/rpm-state/gconf. GConf2, rpm, or filesystem could work.  Should probably be the same as the one that holds the macros.  The macro provider must be present at build time, though, while the directory provider must be present at install time.  So we have to be sure that wherever we stick this is present at both.  (For instance, by adding a BuildRequire: GConf2).