Author: jkupec
Date: Sun May 20 23:16:18 2007
New Revision: 5571
URL: http://svn.opensuse.org/viewcvs/zypp?rev=5571&view=rev
Log:
- PatchFileReader complete
- using data::PackageAtom for /patch/atoms/package/* data for now
Modified:
trunk/libzypp/devel/devel.jkupec/YUMParser.cc
trunk/libzypp/zypp/data/ResolvableData.cc
trunk/libzypp/zypp/data/ResolvableData.h
trunk/libzypp/zypp/parser/yum/FileReaderBase.h
trunk/libzypp/zypp/parser/yum/PatchFileReader.cc
trunk/libzypp/zypp/parser/yum/PatchFileReader.h
Modified: trunk/libzypp/devel/devel.jkupec/YUMParser.cc
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/devel/devel.jkupec/YUMParser.cc?rev=5571&r1=5570&r2=5571&view=diff
==============================================================================
--- trunk/libzypp/devel/devel.jkupec/YUMParser.cc (original)
+++ trunk/libzypp/devel/devel.jkupec/YUMParser.cc Sun May 20 23:16:18 2007
@@ -152,7 +152,7 @@
}
default:
{
- DBG << "oh yeah, time will come, when we will parse "
+ WAR << "Don't know how to read "
<< job.type() << " file "
<< job.filename() << endl;
}
Modified: trunk/libzypp/zypp/data/ResolvableData.cc
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/data/ResolvableData.cc?rev=5571&r1=5570&r2=5571&view=diff
==============================================================================
--- trunk/libzypp/zypp/data/ResolvableData.cc (original)
+++ trunk/libzypp/zypp/data/ResolvableData.cc Sun May 20 23:16:18 2007
@@ -28,6 +28,11 @@
IMPL_PTR_TYPE(Package);
IMPL_PTR_TYPE(SrcPackage);
+IMPL_PTR_TYPE(DeltaRpm);
+IMPL_PTR_TYPE(PatchRpm);
+IMPL_PTR_TYPE(PackageAtom);
+IMPL_PTR_TYPE(BaseVersion);
+
std::ostream & ResObject::dumpOn( std::ostream & str ) const
{
Modified: trunk/libzypp/zypp/data/ResolvableData.h
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/data/ResolvableData.h?rev=5571&r1=5570&r2=5571&view=diff
==============================================================================
--- trunk/libzypp/zypp/data/ResolvableData.h (original)
+++ trunk/libzypp/zypp/data/ResolvableData.h Sun May 20 23:16:18 2007
@@ -211,7 +211,7 @@
/**
* The set of all atoms building the patch. These can be either
- * \ref Atom, \ref Message or \ref Script.
+ * \ref PackageAtom, \ref Message or \ref Script.
*/
std::set atoms;
};
@@ -298,7 +298,7 @@
class Packagebase : public ResObject
{
public:
- enum PackageType { BIN, SRC };
+ enum PackageType { BIN, SRC, ATOM };
virtual PackageType packageType() const = 0;
public:
@@ -360,6 +360,75 @@
{
virtual PackageType packageType() const { return SRC; }
};
+
+ // --- ---------------------------------------------------------------------
+ // --- the following are the data structures for storing YUM package atom
+ // --- metadata (part of patch support). This is probably subject to change
+ // --- in near future.
+ // --- ---------------------------------------------------------------------
+
+ DEFINE_PTR_TYPE(BaseVersion);
+ /** Patch RPM baseversion */
+ struct BaseVersion : public base::ReferenceCounted, private base::NonCopyable
+ {
+ Edition edition;
+ };
+
+ /** Shared RPM attributes */
+ struct RpmBase : public base::ReferenceCounted, private base::NonCopyable
+ {
+ // Base <patchrpm>/<deltarpm> element attributes
+
+ Arch attr_arch;
+ std::string attr_filename;
+ std::string attr_md5sum;
+ ByteCount attr_downloadSize;
+ Date attr_buildTime;
+
+ // Shared RPM data
+
+ Location location;
+ Date buildTime;
+ Date fileTime;
+ ByteCount archiveSize; // ??
+ };
+
+ DEFINE_PTR_TYPE(PatchRpm);
+ /** Patch RPM data object */
+ struct PatchRpm : RpmBase
+ {
+ std::set baseVersions;
+ };
+
+ DEFINE_PTR_TYPE(DeltaRpm);
+ /** Delta RPM data object */
+ struct DeltaRpm : RpmBase
+ {
+ struct DeltaBaseVersion : BaseVersion
+ {
+ Date buildTime;
+ CheckSum checkSum;
+ std::string sequenceInfo;
+ };
+
+ DeltaBaseVersion baseVersion;
+ };
+
+ DEFINE_PTR_TYPE(PackageAtom);
+ /**
+ * Data Object for YUM package atom.
+ *
+ * \see zypp/parser/yum/schema/patch.rng
+ */
+ struct PackageAtom : public Package
+ {
+ std::set patchRpms;
+ std::set deltaRpms;
+ // TODO support mulitple licenses (licenseToConfirm)
+ };
+
+ // --- ----------END--YUM-package-atom-metadata-----------------------------
+
///////////////////////////////////////////////////////////////////
} // namespace data
Modified: trunk/libzypp/zypp/parser/yum/FileReaderBase.h
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/parser/yum/FileReaderBase.h?rev=5571&r1=5570&r2=5571&view=diff
==============================================================================
--- trunk/libzypp/zypp/parser/yum/FileReaderBase.h (original)
+++ trunk/libzypp/zypp/parser/yum/FileReaderBase.h Sun May 20 23:16:18 2007
@@ -41,7 +41,10 @@
tag_patch,
tag_atoms,
tag_script,
- tag_message
+ tag_message,
+ tag_pkgfiles,
+ tag_deltarpm,
+ tag_patchrpm
};
/**
@@ -84,7 +87,6 @@
public:
FileReaderBase();
- virtual ~FileReaderBase() {}
/**
* Process package node and its subtree.
@@ -93,7 +95,7 @@
* \return true if the package node or current subnode has been consumed
* (no further processing is required), false otherwise.
*/
- virtual bool consumePackageNode(xml::Reader & reader_r, data::Package_Ptr & package_ptr);
+ bool consumePackageNode(xml::Reader & reader_r, data::Package_Ptr & package_ptr);
/**
* Function for processing all <code>format</code> tag subtree nodes.
@@ -121,6 +123,8 @@
/** Move to parent tag in the \ref _tagpath. */
void toParentTag() { _tagpath.remove(); }
+ const TagPath & tagPath() const { return _tagpath; }
+
private:
Modified: trunk/libzypp/zypp/parser/yum/PatchFileReader.cc
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/parser/yum/PatchFileReader.cc?rev=5571&r1=5570&r2=5571&view=diff
==============================================================================
--- trunk/libzypp/zypp/parser/yum/PatchFileReader.cc (original)
+++ trunk/libzypp/zypp/parser/yum/PatchFileReader.cc Sun May 20 23:16:18 2007
@@ -153,7 +153,8 @@
// xpath: /patch
if (reader_r->name() == "patch")
{
- // TODO some validation? e.g. _patch->atoms.size() > 0
+ if (!_patch->atoms.size())
+ WAR << "No atoms found for patch " << _patch->name << " " << _patch->edition << endl;
if (_callback)
_callback(handoutPatch());
@@ -172,12 +173,8 @@
bool PatchFileReader::consumeAtomsNode(Reader & reader_r)
{
// consumePackageNode
- if (isBeingProcessed(tag_package))
- {
- data::Package_Ptr package_ptr = zypp::dynamic_pointer_castdata::Package(_tmpResObj);
- if (package_ptr && consumePackageNode(reader_r, package_ptr))
- return true;
- }
+ if (isBeingProcessed(tag_package) && consumePackageNode(reader_r))
+ return true;
// consumeMessageNode
else if (isBeingProcessed(tag_message) && consumeMessageNode(reader_r))
return true;
@@ -194,19 +191,20 @@
// remember that we are processing package from now on
// xpath: /patch/atoms/package/*
tag(tag_package);
- // this object will be used by FileReaderBase::consumePackageNodes()
- // which needs Package object, not Atom. But it will be saved as Atom
- // after it's been filled.
- data::Package_Ptr package = new data::Package;
- consumePackageNode(reader_r, package);
- _tmpResObj = package;
+ // DBG << "Atom node, tagpath: " << tagPath() << endl;
+ _tmpResObj = new data::PackageAtom;
+ // process also the package node attributes
+ consumePackageNode(reader_r);
return true;
}
// xpath: /patch/atoms/message
if (reader_r->name() == "message")
{
+ // remember that we are processing message from now on
+ // xpath: /patch/atoms/message/*
tag(tag_message);
+ // DBG << "Message node, tagpath: " << tagPath() << endl;
_tmpResObj = new data::Message;
return true;
}
@@ -214,7 +212,10 @@
// xpath: /patch/atoms/script
if (reader_r->name() == "script")
{
+ // remember that we are processing script from now on
+ // xpath: /patch/atoms/script/*
tag(tag_script);
+ // DBG << "Script node, tagpath: " << tagPath() << endl;
_tmpResObj = new data::Script;
return true;
}
@@ -224,16 +225,9 @@
// xpath: /patch/atoms/package
if (reader_r->name() == "package")
{
- data::Atom_Ptr atom_ptr = new data::Atom;
- copyPackageAtomFromTmpObj(atom_ptr);
- _patch->atoms.insert(atom_ptr);
-
- DBG << "Atom " << atom_ptr->name << " " << atom_ptr->edition << " successfully read." << endl;
-
- // get rid of the old package object
- data::ResObject_Ptr tmp;
- tmp.swap(_tmpResObj);
+ // DBG << "Atom " << _tmpResObj->name << " " << _tmpResObj->edition << " successfully read." << endl;
+ saveAtomInPatch();
toParentTag(); // back to processing of previous tag (atoms)
return true;
}
@@ -241,7 +235,7 @@
// xpath: /patch/atoms/message
if (reader_r->name() == "message")
{
- DBG << "Message " << _tmpResObj->name << " " << _tmpResObj->edition << " successfully read." << endl;
+ // DBG << "Message " << _tmpResObj->name << " " << _tmpResObj->edition << " successfully read." << endl;
saveAtomInPatch();
toParentTag(); // back to processing of previous tag (atoms)
@@ -251,7 +245,7 @@
// xpath: /patch/atoms/script
if (reader_r->name() == "script")
{
- DBG << "Script " << _tmpResObj->name << " " << _tmpResObj->edition << " successfully read." << endl;
+ // DBG << "Script " << _tmpResObj->name << " " << _tmpResObj->edition << " successfully read." << endl;
saveAtomInPatch();
toParentTag(); // back to processing of previous tag (atoms)
@@ -271,24 +265,269 @@
// --------------------------------------------------------------------------
-/* bool PatchFileReader::consumePackageNode(Reader & reader_r)
+ bool PatchFileReader::consumePackageNode(Reader & reader_r)
{
- data::Package_Ptr package_ptr = zypp::dynamic_pointer_castdata::Package(_tmpResObj);
- if (package_ptr && consumePackageNode(reader_r, package_ptr))
+ if (isBeingProcessed(tag_patchrpm) && consumePatchrpmNode(reader_r))
return true;
-
+ else if (isBeingProcessed(tag_deltarpm) && consumeDeltarpmNode(reader_r))
+ return true;
+
if (reader_r->nodeType() == XML_READER_TYPE_ELEMENT)
{
// TODO package extensions -> pkg-files, license-to-confirm
- if (reader_r->name() == "")
+ // xpath: /patch/atoms/package/pkgfiles
+ if (reader_r->name() == "pkgfiles")
+ {
+ tag(tag_pkgfiles);
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/pkgfiles/patchrpm (*)
+ if (reader_r->name() == "patchrpm")
+ {
+ tag(tag_patchrpm);
+ _patchrpm = new data::PatchRpm;
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/pkgfiles/deltarpm (*)
+ if (reader_r->name() == "deltarpm")
+ {
+ tag(tag_deltarpm);
+ _deltarpm = new data::DeltaRpm;
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/license-to-confirm (*)
+ if (reader_r->name() == "license-to-confirm")
+ {
+ DBG << "got license-to-confirm, lang: " << reader_r->getAttribute("lang").asString();
+
+ // no way to determine which translation is associated
+ // with another, all previous will be overwritten with
+ // the last one
+ // TODO introduce an identifier in YUM data
+ // TODO make this rely on tag order as a temporary solution?
+
+ _tmpResObj->licenseToConfirm.setText(
+ reader_r.nodeText().asString(),
+ Locale(reader_r->getAttribute("lang").asString()));
+
+ return true;
+ }
+ }
+
+ else if (reader_r->nodeType() == XML_READER_TYPE_END_ELEMENT)
+ {
+ // xpath: /patch/atoms/package/pkgfiles
+ if (reader_r->name() == "pkgfiles")
+ {
+ toParentTag();
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/pkgfiles/patchrpm (*)
+ if (reader_r->name() == "patchrpm")
+ {
+ data::PatchRpm_Ptr tmp;
+ tmp.swap(_patchrpm);
+ data::PackageAtom_Ptr patom_ptr = zypp::dynamic_pointer_castdata::PackageAtom(_tmpResObj);
+ if (patom_ptr)
+ patom_ptr->patchRpms.insert(tmp);
+ toParentTag();
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/pkgfiles/deltarpm (*)
+ if (reader_r->name() == "deltarpm")
{
+ data::DeltaRpm_Ptr tmp;
+ tmp.swap(_deltarpm);
+ data::PackageAtom_Ptr patom_ptr = zypp::dynamic_pointer_castdata::PackageAtom(_tmpResObj);
+ if (patom_ptr)
+ patom_ptr->deltaRpms.insert(tmp);
+ toParentTag();
return true;
}
}
+ // FileReaderBase::consumePackageNode() call here, otherwise the pkgfiles
+ // would not be read.
+ data::Package_Ptr package_ptr = zypp::dynamic_pointer_castdata::Package(_tmpResObj);
+ if (package_ptr)
+ {
+ // xpath: /patch/atoms/package/* (except pkgfiles/* and license-to-confirm) (*)
+ if (isBeingProcessed(tag_package))
+ return FileReaderBase::consumePackageNode(reader_r, package_ptr);
+ }
+ else
+ {
+ ZYPP_THROW(Exception("Error in parser code. Package atom object not found."));
+ }
+
return true;
}
-*/
+
+ // --------------------------------------------------------------------------
+
+ bool PatchFileReader::consumePatchrpmNode(Reader & reader_r)
+ {
+ if (reader_r->nodeType() == XML_READER_TYPE_ELEMENT)
+ {
+ // xpath: /patch/atoms/package/patchrpm/location
+ if (reader_r->name() == "location")
+ {
+ _patchrpm->location.filePath = reader_r->getAttribute("href").asString();
+ // ignoring attribute 'base'
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/patchrpm/checksum
+ if (reader_r->name() == "checksum")
+ {
+ _patchrpm->location.fileChecksum = CheckSum(
+ reader_r->getAttribute("type").asString(),
+ reader_r.nodeText().asString());
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/patchrpm/time
+ if (reader_r->name() == "time")
+ {
+ _patchrpm->buildTime =
+ Date(reader_r->getAttribute("build").asString());
+
+ _patchrpm->fileTime =
+ Date(reader_r->getAttribute("file").asString());
+
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/patchrpm/size
+ if (reader_r->name() == "size")
+ {
+ // size of the rpm file
+ _patchrpm->location.fileSize = str::strtonumByteCount::SizeType(
+ reader_r->getAttribute("package").asString());
+
+ // size of ??
+ _patchrpm->archiveSize = str::strtonumByteCount::SizeType(
+ reader_r->getAttribute("archive").asString());
+
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/patchrpm/baseversion (+)
+ if (reader_r->name() == "baseversion")
+ {
+ data::BaseVersion_Ptr base_ptr = new data::BaseVersion;
+
+ // size of the rpm file
+ base_ptr->edition = Edition(reader_r->getAttribute("ver").asString(),
+ reader_r->getAttribute("rel").asString(),
+ reader_r->getAttribute("epoch").asString());
+
+ _patchrpm->baseVersions.insert(base_ptr);
+ return true;
+ }
+ }
+
+ else if (reader_r->nodeType() == XML_READER_TYPE_END_ELEMENT)
+ {
+ // xpath: /patch/atoms/package/pkgfiles/patchrpm
+ if (reader_r->name() == "patchrpm")
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // --------------------------------------------------------------------------
+
+ bool PatchFileReader::consumeDeltarpmNode(Reader & reader_r)
+ {
+ if (reader_r->nodeType() == XML_READER_TYPE_ELEMENT)
+ {
+ // xpath: /patch/atoms/package/deltarpm/location
+ if (reader_r->name() == "location")
+ {
+ _deltarpm->location.filePath = reader_r->getAttribute("href").asString();
+ // ignoring attribute 'base'
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/deltarpm/checksum
+ if (reader_r->name() == "checksum")
+ {
+ _deltarpm->location.fileChecksum = CheckSum(
+ reader_r->getAttribute("type").asString(),
+ reader_r.nodeText().asString());
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/deltarpm/time
+ if (reader_r->name() == "time")
+ {
+ _deltarpm->buildTime =
+ Date(reader_r->getAttribute("build").asString());
+
+ _deltarpm->fileTime =
+ Date(reader_r->getAttribute("file").asString());
+
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/deltarpm/size
+ if (reader_r->name() == "size")
+ {
+ // size of the rpm file
+ _deltarpm->location.fileSize = str::strtonumByteCount::SizeType(
+ reader_r->getAttribute("package").asString());
+
+ // size of ??
+ _deltarpm->archiveSize = str::strtonumByteCount::SizeType(
+ reader_r->getAttribute("archive").asString());
+
+ return true;
+ }
+
+ // xpath: /patch/atoms/package/deltarpm/baseversion
+ if (reader_r->name() == "baseversion")
+ {
+ // size of the rpm file
+ _deltarpm->baseVersion.edition = Edition(reader_r->getAttribute("ver").asString(),
+ reader_r->getAttribute("rel").asString(),
+ reader_r->getAttribute("epoch").asString());
+ // checksum
+ _deltarpm->baseVersion.checkSum =
+ CheckSum("md5", reader_r->getAttribute("md5sum").asString());
+
+ // build time
+ _deltarpm->baseVersion.buildTime =
+ Date(reader_r->getAttribute("buildtime").asString());
+
+ // sequence info
+ _deltarpm->baseVersion.sequenceInfo =
+ reader_r->getAttribute("sequence_info").asString();
+
+ return true;
+ }
+ }
+
+ else if (reader_r->nodeType() == XML_READER_TYPE_END_ELEMENT)
+ {
+ // xpath: /patch/atoms/package/pkgfiles/deltarpm
+ if (reader_r->name() == "deltarpm")
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
// --------------------------------------------------------------------------
bool PatchFileReader::consumeMessageNode(Reader & reader_r)
@@ -387,10 +626,10 @@
// TODO xpath: /patch/atoms/script/do-location
if (reader_r->name() == "do-location")
{
- // xsd:anyURI
-// script->doScriptLocation.filepath = reader_r->getAttribute("xml:base").asString();
- // xsd:anyURI
-// script->doScriptLocation.? = reader_r->getAttribute("href").asString();
+ // xsd:anyURI do script file path base (is this used at all?)
+ // ignoring reader_r->getAttribute("xml:base").asString();
+ // xsd:anyURI do script file path
+ script->doScriptLocation.filePath = reader_r->getAttribute("href").asString();
return true;
}
@@ -406,10 +645,10 @@
// TODO xpath: /patch/atoms/script/undo-location
if (reader_r->name() == "undo-location")
{
- // xsd:anyURI
-// script->undoScriptLocation.filepath = reader_r->getAttribute("xml:base").asString();
- // xsd:anyURI
-// script->undoScriptLocation.? = reader_r->getAttribute("href").asString();
+ // xsd:anyURI undo script file path base (is this used at all?)
+ // ignoring reader_r->getAttribute("xml:base").asString();
+ // xsd:anyURI undo script file path
+ script->undoScriptLocation.filePath = reader_r->getAttribute("href").asString();
return true;
}
@@ -453,25 +692,6 @@
_patch->atoms.insert(tmp);
}
- // --------------------------------------------------------------------------
-
- void PatchFileReader::copyPackageAtomFromTmpObj(data::Atom_Ptr & atom_ptr) const
- {
- atom_ptr->name = _tmpResObj->name;
- atom_ptr->edition = _tmpResObj->edition;
- atom_ptr->arch = _tmpResObj->arch;
- atom_ptr->deps = _tmpResObj->deps;
- atom_ptr->vendor = _tmpResObj->vendor;
- atom_ptr->installedSize = _tmpResObj->installedSize;
- atom_ptr->buildTime = _tmpResObj->buildTime;
- atom_ptr->installOnly = _tmpResObj->installOnly;
- atom_ptr->summary = _tmpResObj->summary;
- atom_ptr->description = _tmpResObj->description;
- atom_ptr->licenseToConfirm = _tmpResObj->licenseToConfirm;
- atom_ptr->insnotify = _tmpResObj->insnotify;
- atom_ptr->delnotify = _tmpResObj->delnotify;
- }
-
} // ns yum
} // ns parser
Modified: trunk/libzypp/zypp/parser/yum/PatchFileReader.h
URL: http://svn.opensuse.org/viewcvs/zypp/trunk/libzypp/zypp/parser/yum/PatchFileReader.h?rev=5571&r1=5570&r2=5571&view=diff
==============================================================================
--- trunk/libzypp/zypp/parser/yum/PatchFileReader.h (original)
+++ trunk/libzypp/zypp/parser/yum/PatchFileReader.h Sun May 20 23:16:18 2007
@@ -70,6 +70,35 @@
bool consumeAtomsNode(xml::Reader & reader_r);
/**
+ * Process <tt>package</tt> node and all of its children. This method
+ * uses \ref FileReaderBase::consumePackageNode(xml::Reader,data::Package_Ptr)
+ * method and adds <tt>pkgfiles</tt> element processing.
+ *
+ * \param reader_r XML file reader reading the patch file.
+ * \return true if current node has been completely processed, false
+ * if additional processing is required outside of the method.
+ */
+ bool consumePackageNode(xml::Reader & reader_r);
+
+ /**
+ * Process <tt>patchrpm</tt> node and all of its children.
+ *
+ * \param reader_r XML file reader reading the patch file.
+ * \return true if current node has been completely processed, false
+ * if additional processing is required outside of the method.
+ */
+ bool consumePatchrpmNode(xml::Reader & reader_r);
+
+ /**
+ * Process <tt>deltarpm</tt> node and all of its children.
+ *
+ * \param reader_r XML file reader reading the patch file.
+ * \return true if current node has been completely processed, false
+ * if additional processing is required outside of the method.
+ */
+ bool consumeDeltarpmNode(xml::Reader & reader_r);
+
+ /**
* Process <tt>message</tt> node and all of its children.
*
* \param reader_r XML file reader reading the patch file.
@@ -118,8 +147,19 @@
*/
data::Patch_Ptr _patch;
- /** Pointer to an atom currently being read. */
+ /**
+ * Pointer to an atom currently being read. This can be either
+ * a \ref data::PackageAtom, \ref data::Message, or \ref data::Script.
+ *
+ * \see data::Patch::atoms
+ */
data::ResObject_Ptr _tmpResObj;
+
+ /** Data object for storing patchrpm data */
+ data::PatchRpm_Ptr _patchrpm;
+
+ /** Data object for storing deltarpm data */
+ data::DeltaRpm_Ptr _deltarpm;
};
--
To unsubscribe, e-mail: zypp-commit+unsubscribe@opensuse.org
For additional commands, e-mail: zypp-commit+help@opensuse.org