Revision: 25765
http://sourceforge.net/p/gar/code/25765
Author: cgrzemba
Date: 2016-06-07 14:19:58 +0000 (Tue, 07 Jun 2016)
Log Message:
-----------
add some IPS packaging stuff
Modified Paths:
--------------
csw/mgar/gar/v2/bin/pathfilter.py
csw/mgar/gar/v2/gar.pkg.mk
csw/mgar/gar/v2/transforms/defaults
Added Paths:
-----------
csw/mgar/gar/v2/pkglint/
csw/mgar/gar/v2/pkglint/__init__.py
csw/mgar/gar/v2/pkglint/opencsw.py
csw/mgar/gar/v2/pkglintrc
csw/mgar/gar/v2/transforms/remove-os-version
csw/mgar/gar/v2/transforms/remove-os-version.notactive
Modified: csw/mgar/gar/v2/bin/pathfilter.py
===================================================================
--- csw/mgar/gar/v2/bin/pathfilter.py 2016-06-07 12:38:37 UTC (rev 25764)
+++ csw/mgar/gar/v2/bin/pathfilter.py 2016-06-07 14:19:58 UTC (rev 25765)
@@ -8,7 +8,6 @@
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from lib.python import common_constants
-from lib.python import configuration
USAGE = '''%prog [-i path][-x path][-I path][-X path]
Modified: csw/mgar/gar/v2/gar.pkg.mk
===================================================================
--- csw/mgar/gar/v2/gar.pkg.mk 2016-06-07 12:38:37 UTC (rev 25764)
+++ csw/mgar/gar/v2/gar.pkg.mk 2016-06-07 14:19:58 UTC (rev 25765)
@@ -15,8 +15,14 @@
# use opencsw pakckage db for resolve dependencies for IPS packages
IPS_USE_PKG_DB =
+IPS_GET_DEP =
+# to brake dependency cycles can packages which match pattern be published in
a post cycle
+IPS_2PHASE_PUBLISH =
+IPS_2PHASE_PUBLISH_PATTERN = $(if $(IPS_2PHASE_PUBLISH),%utils %util %tools
%tool)
# prepend this to the package name
IPS_PACKAGE_PREFIX ?= opencsw/
+# on publish cleanup preexisting package in repo
+IPS_RM_SAME_VERS ?= 1
ifeq ($(DEBUG_PACKAGING),)
_DBG=@
@@ -343,7 +349,7 @@
# Make sure the configuration files always have a .CSW suffix and rename the
# configuration files to this if necessary during merge.
-ifneq ($(GAROSREL),5.11)
+ifneq ($(PKGFORMAT),ips)
_EXTRA_PAX_ARGS += $(foreach FILE,$(SAMPLECONF:%\.CSW=%)
$(PRESERVECONF:%\.CSW=%),-s ",^\.\($(FILE)\)$$,.\1\.CSW,p")
endif
@@ -445,7 +451,7 @@
# as argument
define _pkgfiles_exclude
$(strip
- $(foreach S,$(filter-out $(1),$(_PKG_SPECS)),
+ $(foreach S,$(filter-out $(1) $(NOPACKAGE_IPS),$(_PKG_SPECS)),
$(PKGFILES_$(S))
)
)
@@ -454,7 +460,7 @@
define _pkgfiles_include
$(strip
$(PKGFILES_$(1)_SHARED)
- $(PKGFILES_$(1))
+ $(PKGFILES_$(1))
)
endef
@@ -1001,12 +1007,18 @@
_buildpackage: pre-package $(PACKAGE_TARGETS) post-package $(if $(filter-out
0,$(ENABLE_CHECK)),pkgcheck)
# _buildpackage-ips: pre-package $(PACKAGE_TARGETS_IPS) post-package $(if
$(filter-out 0,$(ENABLE_CHECK)),pkgcheck)
-_buildpackage-ips: pre-package $(PACKAGE_TARGETS_IPS) post-package
package-publish
+_buildpackage-ips: pre-package $(PACKAGE_TARGETS_IPS) post-package
package-publish-lib package-publish-other
# generates p5m from proto and publishs
-package-publish:
+# if IPS_2PHASE_PUBLISH publish util and tool packages in a post step
+# package-publish-lib: nowpublish = $(filter-out %utils %util %tools
%tool,$(filter lib%,$(_PKG_SPECS_IPS)))
+# package-publish-other: nowpublish = $(filter-out $(filter-out %utils %util
%tool %tools,$(filter lib%,$(_PKG_SPECS_IPS))),$(_PKG_SPECS_IPS))
+package-publish-lib: nowpublish = $(filter-out
$(IPS_2PHASE_PUBLISH_PATTERN),$(_PKG_SPECS_IPS))
+package-publish-other: nowpublish = $(filter-out $(filter-out
$(IPS_2PHASE_PUBLISH_PATTERN),$(_PKG_SPECS_IPS)),$(_PKG_SPECS_IPS))
+package-publish-%:
+ @echo "PUBLISH: $(nowpublish)"
$(if $(IPS_USE_PKG_DB), \
- $(foreach SPEC,$(_PKG_SPECS_IPS),\
+ $(foreach SPEC,$(nowpublish),\
$(GARBIN)/pkg_resolve $(DEBUG_FLAG) \
--arch "$(GARCH)" \
--os-release "$(SPKG_OSNAME)" \
@@ -1014,12 +1026,13 @@
--pkg-root "$(PKGROOT)" $(SPEC).proto > $(SPEC).p5p, \
cp [email protected] [email protected]))
$(if $(IPS_RM_SAME_VERS),\
- $(foreach SPEC,$(_PKG_SPECS_IPS),\
+ $(foreach SPEC,$(nowpublish),\
pkgrepo remove -s $(SPKG_EXPORT_IPS)
$(IPS_PACKAGE_PREFIX)$(SPEC)@$(IPS_VERSION) || true;))
- $(_DBG)cd $(WORKDIR) && pkgdepend resolve -m $(foreach
SPEC,$(_PKG_SPECS_IPS),$(SPEC).p5p )
- $(foreach SPEC,$(_PKG_SPECS_IPS),\
- ( cd $(WORKDIR) && cp $(SPEC).p5p.res $(SPEC).p5m && \
- pkglint -c /var/tmp/build_$(LOGNAME)/lint-cache -r
$(SPKG_EXPORT_IPS) $(SPEC).p5m ); \
+ @echo "Resolve dependencies for $(nowpublish)"
+ $(_DBG)cd $(WORKDIR) && pkgdepend resolve -m $(foreach
SPEC,$(nowpublish),$(SPEC).p5p )
+ $(foreach SPEC,$(nowpublish),\
+ ( cd $(WORKDIR) && pkgmogrify -I $(GARDIR)transforms
remove-os-version $(SPEC).p5p.res > $(SPEC).p5m && \
+ pkglint -f $(GARDIR)/pkglintrc -c
/var/tmp/build_$(LOGNAME)/lint-cache -r $(SPKG_EXPORT_IPS) $(SPEC).p5m ) && \
pkgsend publish -s $(SPKG_EXPORT_IPS) -d $(SPKG_PKGROOT)
$(WORKDIR)/$(SPEC).p5m; )
_package: validateplatform extract-global merge $(SPKG_DESTDIRS) _buildpackage
@@ -1082,15 +1095,24 @@
@$(foreach COOKIEFILE,$(PACKAGE_TARGETS), test -e
$(COOKIEDIR)/$(COOKIEFILE) ;)
# -- IPS Packaging --
+define _pkgfiles_include_dev
+$(strip
+ $(if $(filter $(PKGFORMAT-$(GAROSREL)),ips),
+ $(if $(filter $(IPS_DEVPKG),$(1)),
+ $(PKGFILES_$(filter %-dev,$(_PKG_SPECS)))
+ )
+ )
+)
+endef
.PRECIOUS: $(WORKDIR)/%.proto
$(WORKDIR)/%.proto: _PKGFILES_EXCLUDE=$(call _pkgfiles_exclude,CSW$*)
$(WORKDIR)/%.proto: _PKGFILES_INCLUDE=$(call _pkgfiles_include,CSW$*)
+$(WORKDIR)/%.proto: _PKGFILES_INCLUDE_DEV=$(call _pkgfiles_include_dev,CSW$*)
$(WORKDIR)/%.proto: $(WORKDIR)
- $(_DBG) @echo "PKG: $(IPS_PACKAGE_PREFIX)$*"
+ $(_DBG) @echo "\nPKG: $(IPS_PACKAGE_PREFIX)$*"
$(_DBG) pkgsend generate $(PKGROOT) >[email protected]
- $(_DBG)if [ -n "$(PKGFILES_CSW$*_SHARED)" -o \
- -n "$(PKGFILES_CSW$*)" -o \
+ $(_DBG)if [ -n "$(_PKGFILES_INCLUDE)" -o \
-n "$(_PKGFILES_EXCLUDE)" -o \
-n "$(ISAEXEC_FILES_CSW$*)" -o \
-n "$(ISAEXEC_FILES)" ]; then \
@@ -1107,7 +1129,7 @@
$(foreach I,$(EXTRA_PKGFILES_INCLUDED)
$(EXTRA_PKGFILES_INCLUDED_CSW$*),-i '$I') \
$(foreach X,$(EXTRA_PKGFILES_EXCLUDED)
$(EXTRA_PKGFILES_EXCLUDED_CSW$*),-x '$X') \
$(foreach FILE,$(_PKGFILES_INCLUDE),-i '$(FILE)') \
- $(if $(_PKGFILES_INCLUDE),-x '.*',$(foreach
FILE,$(_PKGFILES_EXCLUDE),-x '$(FILE)')) \
+ $(if $(_PKGFILES_INCLUDE),$(foreach
FILE,$(_PKGFILES_INCLUDE_DEV),-i '$(FILE)') -x '.*',$(foreach
FILE,$(_PKGFILES_EXCLUDE),-x '$(FILE)')) \
$(foreach IE,$(abspath $(ISAEXEC_FILES_CSW$*)
$(ISAEXEC_FILES)), \
-e '$(IE)=$(dir $(IE))$(ISA_DEFAULT)/$(notdir $(IE))'
\
) \
@@ -1117,21 +1139,22 @@
else \
cp [email protected] [email protected]; \
fi
- $(if $(and $(INITSMF),$(filter $(shell cat
$(WORKDIR)/[email protected]),$(patsubst /%,%,$(INITSMF)))), \
+ $(if $(and $(INITSMF),$(filter $(shell cat [email protected]),$(patsubst
/%,%,$(INITSMF)))), \
ginstall -d $(PKGROOT)/var/svc/manifest/site; \
- svcbundle -o $(PKGROOT)/var/svc/manifest/$(notdir $(INITSMF)).xml
-s service-name=$(notdir $(INITSMF)) -s model=daemon -s
start-method="$(INITSMF) start" -s stop-method="$(INITSMF) stop"; \
- echo "<transform pkg -> emit file owner=root group=sys mode=755
path=var/svc/manifest/site/$(notdir $(INITSMF)).xml>" >> [email protected]; )
+ svcbundle -o $(PKGROOT)/var/svc/manifest/site/$(notdir
$(INITSMF)).xml -s service-name=$(notdir $(INITSMF)) -s model=daemon -s
start-method="$(INITSMF) start" -s stop-method="$(INITSMF) stop"; \
+ @echo "<transform pkg -> emit file owner=root group=sys mode=755
path=var/svc/manifest/site/$(notdir $(INITSMF)).xml>" >> [email protected]; )
$(_DBG)$(foreach DFILE,$(IPS_PKGFILES_DEVEL), echo "<transform file
path=$(patsubst /%,%,$(DFILE)) -> default facet.devel true>" >> [email protected]; )
$(foreach BIT,$(IPS_BYPASS_GENERATE_DEP), echo "<transform file
path=$(patsubst /%,%,$(BIT)) -> default pkg.depend.bypass-generate .*>" >>
[email protected]; )
$(foreach BIT,$(PKGFILES_CSW$*_SHARED), \
echo "<transform file path=$(patsubst /%,%,$(BIT)) -> default
overlay allow>" >> [email protected]; \
echo "<transform file path=$(patsubst /%,%,$(BIT)) -> default
preserve legacy>" >> [email protected] )
- $(foreach PKG,$(filter-out $(_PKG_SPECS),$(RUNTIME_DEP_PKGS_CSW$*)),
echo "<transform pkg -> emit depend fmri=pkg:/$(patsubst CSW%,%,$(PKG))
type=require>" >> [email protected]; )
+ $(if $(IPS_GET_DEP), \
+ $(foreach PKG,$(filter-out $(_PKG_SPECS),$(RUNTIME_DEP_PKGS_CSW$*)),
echo "<transform pkg -> emit depend fmri=pkg:/$(patsubst CSW%,%,$(PKG))
type=require>" >> [email protected]; ))
$(foreach CONF,$(PRESERVECONF), echo "<transform file path=$(patsubst
/%,%,$(CONF)) -> default preserve renamenew>" >> [email protected]; )
mv [email protected] $@
-
+
IPS_META_CLASSIFICATION ?= Applications/Accessories
IPS_META_SUMMARY ?= $(if $(SPKG_DESC_CSW$*),$(SPKG_DESC_CSW$*),$(DESCRIPTION))
IPS_META_DESCRIPTION ?= $(DESCRIPTION)
@@ -1140,12 +1163,18 @@
.PRECIOUS: $(WORKDIR)/%.meta
$(WORKDIR)/%.meta: cswpkgname = CSW$(subst _,-,$*)
$(WORKDIR)/%.meta: $(WORKDIR)
+ $(if $(PKGFILES_$(filter %-dev, $(_PKG_SPECS))),,$(error dev package is
catch all package, since IPS we do not provide devel and doc packages, you have
to specify witch packages gets the devel files by remove there PKGFILES_CSW
definitions))
+ $(if $(IPS_DEVPKG),,$(error Assign development files to a package, by
setting IPS_DEVPKG = CSWpackagename))
+ $(foreach P,$(filter-out $(IPS_DEVPKG) %-dev, $(_PKG_SPECS)), $(if
$(PKGFILES_$(P)),,$(error $(P) is catch all package, since IPS we do not
provide devel and doc packages, only the IPS_DEVPKG can be a catchall package)))
$(if $(filter %/,$(IPS_PACKAGE_PREFIX)),,$(error IPS_PACKAGE_PREFIX
must ending in a / wheres this did not: $(IPS_PACKAGE_PREFIX)))
$(_DBG)(echo "set name=pkg.fmri
value=$(IPS_PACKAGE_PREFIX)$*@$(IPS_VERSION)"; \
echo "set name=pkg.summary value=\"$(IPS_META_SUMMARY)\""; \
echo "set name=pkg.description value=\"$(IPS_META_DESCRIPTION)\""; \
echo "set name=info.classification
value=org.opensolaris.category.2008:$(IPS_META_CLASSIFICATION)"; \
echo "<transform pkg -> emit legacy arch=$(GARCH) category=\"$(if
$(CATEGORY),$(CATEGORY),application)\" desc=\"$(SPKG_DESC_$(cswpkgname))\"
name=\"$(cswpkgname)\" pkg=$(cswpkgname) variant.arch=$(GARCH) vendor=\"$(call
pkgvar,SPKG_VENDOR,$(cswpkgname))\" version=$(call
pkgvar,SPKG_VERSION,$(cswpkgname)),$(call pkgvar,SPKG_REVSTAMP,$(cswpkgname))
hotline=\"http://www.opencsw.org/bugtrack/\">"; \
+ $(if $(filter $(IPS_DEVPKG),$(cswpkgname)), \
+ $(foreach D,$(filter %-dev, $(_PKG_SPECS)), \
+ echo "<transform pkg -> emit legacy arch=$(GARCH) category=\"$(if
$(CATEGORY),$(CATEGORY),application)\" desc=\"$(SPKG_DESC_$(cswpkgname)),
developer\" name=\"$(D)\" pkg=$(D) variant.arch=$(GARCH) vendor=\"$(call
pkgvar,SPKG_VENDOR,$(cswpkgname))\" version=$(call
pkgvar,SPKG_VERSION,$(cswpkgname)),$(call pkgvar,SPKG_REVSTAMP,$(cswpkgname))
hotline=\"http://www.opencsw.org/bugtrack/\">"; )) \
echo "<transform pkg -> emit license $(call licensedir,CSW$(subst
_,-,$*))/license license=\"see license file\">"; \
$(_CATEGORY_IPS_META) ; \
) >$@
Added: csw/mgar/gar/v2/pkglint/__init__.py
===================================================================
--- csw/mgar/gar/v2/pkglint/__init__.py (rev 0)
+++ csw/mgar/gar/v2/pkglint/__init__.py 2016-06-07 14:19:58 UTC (rev 25765)
@@ -0,0 +1,22 @@
+#
+# 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) 2010, Oracle and/or its affiliates. All rights reserved.
+#
Added: csw/mgar/gar/v2/pkglint/opencsw.py
===================================================================
--- csw/mgar/gar/v2/pkglint/opencsw.py (rev 0)
+++ csw/mgar/gar/v2/pkglint/opencsw.py 2016-06-07 14:19:58 UTC (rev 25765)
@@ -0,0 +1,83 @@
+#!/usr/bin/python
+#
+# 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) Carsten Grzemba
+#
+
+import pkg.lint.base as base
+import subprocess as sp
+import os
+
+class OpenCSWActionChecker(base.ActionChecker):
+ """An OpenCSW-specific class to check actions."""
+
+ name = "opencsw.action"
+
+ def __init__(self, config):
+ self.description = _(
+ "checks OpenCSW packages for common action errors")
+ super(OpenCSWActionChecker, self).__init__(config)
+
+ def split_packages(self, manifest, engine, pkglint_id="001"):
+ """Warn if there shared libries in standard path
+ """
+ split_packages.pkglint_desc = _("Package should split out subpackages for
shared libraries")
+
+class OpenCSWManifestChecker(base.ManifestChecker):
+ """An opencsw.org-specific class to check manifests."""
+
+ name = "opencsw.manifest"
+
+ def __init__(self, config):
+ self.description = _(
+ "checks OpenCSW packages for common errors")
+ super(OpenCSWManifestChecker, self).__init__(config)
+
+ def recipe_uncommited(self, manifest, engine, pkglint_id="001"):
+ """Warn when a build recipe is not commited
+ """
+ p = sp.Popen("cd ../../.. && svn st --ignore-externals", shell=True,
stdout=sp.PIPE,stderr=sp.PIPE)
+ p.wait()
+ err = p.stderr.read()
+ if len(err) > 0:
+ engine.error(
+ _("SVN error for {pkg} recipe on path
{path}\n{msg}").format(pkg=manifest.fmri, path=os.path.abspath(''), msg=err),
+ msgid="{0}{1}.1".format(self.name, pkglint_id))
+ else:
+ if p.stdout.read():
+ engine.warning(
+ _("Build recipe should commited for publish
{pkg}").format(pkg=manifest.fmri),
+ msgid="{0}{1}.1".format(self.name, pkglint_id))
+ recipe_uncommited.pkglint_desc = _("Build recipe should commited to
sourceforge")
+
+
+ def packageprefixname_notset(self, manifest, engine, pkglint_id="002"):
+ """ set name=pkg.fmri value=diagnotic/[email protected]
+
+ """
+
+ if manifest.fmri.get_name().find('/',1) < 0 :
+ engine.error(_("IPS_PACKAGE_PREFIX must set in build recipe,
missing prefix in {fmri}").format(fmri=manifest.fmri),
+ msgid="%s%s.2" % (self.name,
pkglint_id))
+
+ packageprefixname_notset.pkglint_desc = _( "build recipe must set package
name prefix for package FMRI" )
Added: csw/mgar/gar/v2/pkglintrc
===================================================================
--- csw/mgar/gar/v2/pkglintrc (rev 0)
+++ csw/mgar/gar/v2/pkglintrc 2016-06-07 14:19:58 UTC (rev 25765)
@@ -0,0 +1,45 @@
+[pkglint]
+
+# Whether to show the progress tracker during lint runs
+use_progress_tracker = True
+
+# The default log level at which to start emitting messages
+# log levels are, in order of increasing priority,
+# DEBUG, INFO, WARNING, ERROR, CRITICAL
+log_level = INFO
+
+# Perform checks that may only make sense for published packages.
+do_pub_checks = True
+
+# pkglint.ext.* keys indicate python modules that should be
+# automatically loaded and check methods exectuted during
+# each lint run.
+
+# key = python package implementing those checks
+# pkglint.ext.other = org.foo.barcheck
+
+# List modules or methods which should be excluded from
+# execution during each lint run.
+pkglint.exclude = pkg.lint.opensolaris
+
+# The version pattern we use when searching for manifests
+# for a given build (only when using the -b flag to pkglint)
+version.pattern = *,5.11-0.
+
+# The path used for info.classification attribute checks
+info_classification_path = /usr/share/lib/pkg/opensolaris.org.sections
+
+# Whether to ignore publisher differences when comparing package versions
+ignore_different_publishers = True
+
+#
+# The following are parameters that are passed to individual lint checks
+#
+
+# dependencies which may be missing at runtime
+pkglint.action005.1.missing-deps =
+
+# whether to log INFO messages when a pkg.linted action/manifest trips a check
+pkglint001.5.report-linted = True
+
+pkglint.ext.content = pkglint.opencsw
Modified: csw/mgar/gar/v2/transforms/defaults
===================================================================
--- csw/mgar/gar/v2/transforms/defaults 2016-06-07 12:38:37 UTC (rev 25764)
+++ csw/mgar/gar/v2/transforms/defaults 2016-06-07 14:19:58 UTC (rev 25765)
@@ -16,11 +16,15 @@
<transform file path=var/svc/manifest/.*\.xml$ -> default restart_fmri
svc:/system/manifest-import:default>
<transform file path=.*lib/.+\.a$ -> default facet.devel all>
<transform file path=.*lib/.+\.la$ -> default facet.devel all>
-<transform file path=.*lib/.+\.so$ -> default facet.devel all>
-<transform file path=.*lib(/(amd64|sparv9))?/pkgconfig(/.*)? -> default
facet.devel all>
+<transform file path=.*lib/.+/.+\.so$ -> default facet.devel false>
+<transform link path=.*lib/.+\.so$ -> default facet.devel all>
+<transform dir file link hardlink path=.*/pkgconfig(/.+\.pc){0,1}$ -> \
+ default facet.devel all>
<transform file path=.*include/.* -> default facet.devel all>
-<transform file path=.*aclocal/.* -> default facet.devel all>
+<transform dir file link hardlink path=.*/aclocal(/.*\.m4){0,1}$ -> \
+ default facet.devel all>
<transform file path=.*man3/.+ -> default facet.devel all>
<transform file path=.*man1/.+-config$ -> default facet.devel all>
<transform file path=.*bin/.+-config$ -> default facet.devel all>
-
+<transform file link hardlink path=.*/lib/llib-.* -> default facet.devel all>
+<transform dir file link hardlink -> delete facet.devel false>
Added: csw/mgar/gar/v2/transforms/remove-os-version
===================================================================
Added: csw/mgar/gar/v2/transforms/remove-os-version.notactive
===================================================================
--- csw/mgar/gar/v2/transforms/remove-os-version.notactive
(rev 0)
+++ csw/mgar/gar/v2/transforms/remove-os-version.notactive 2016-06-07
14:19:58 UTC (rev 25765)
@@ -0,0 +1 @@
+<transform depend -> edit fmri "(.*@[0-9\.]*)-.*" "\1">
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.