steffen: server/utilities/rpmsort main.cpp, NONE, 1.1 rpmsort.pro, NONE, 1.1
cvs at intevation.de
cvs at intevation.de
Tue Jul 19 21:29:20 CEST 2005
Author: steffen
Update of /kolabrepository/server/utilities/rpmsort
In directory doto:/tmp/cvs-serv15571/rpmsort
Added Files:
main.cpp rpmsort.pro
Log Message:
I needed help with the RPM dependencies. This tool can help a little...
--- NEW FILE: main.cpp ---
/*
* Helper app to figure out the order which RPMs
* must be installed to satisfy dependencies.
*
* Uses the 00INDEX.rdf files from OpenPKG
*
* (c) 2005 Steffen Hansen <steffen at kdab.net>
*/
#include <QCoreApplication>
#include <QDomElement>
#include <QFile>
#include <QDebug>
#include <QMap>
#include <QSet>
#include <QStringList>
#include <iostream>
struct RPMNode {
QString name;
QString about;
QString version;
QString release;
QSet<QString> requires;
QSet<QString> provides;
void dumpNode() const {
std::cout << qPrintable(name) << " [";
for( QSet<QString>::const_iterator it = requires.constBegin();
it != requires.constEnd(); ++it ) {
std::cout << " " << qPrintable(*it);
}
std::cout << " ]" << std::endl;
}
};
class RPMSorter {
public:
void clear();
bool addFrom( QIODevice* device );
void dumpNodes() const;
void dumpNodes( const QMap<QString,RPMNode>& ) const;
QStringList sort() const;
private:
QMap<QString,RPMNode> nodes;
};
void RPMSorter::clear()
{
nodes.clear();
}
bool RPMSorter::addFrom( QIODevice* device )
{
QString errorStr;
int errorLine;
int errorColumn;
QDomDocument domDocument;
if (!domDocument.setContent(device, true, &errorStr, &errorLine,
&errorColumn)) {
qFatal( "Parse error at line %d, column %d:\n%s",
errorLine, errorColumn, qPrintable(errorStr));
return false;
}
QDomElement root = domDocument.documentElement();
if( root.tagName() != "RDF" ) {
qFatal("Root node is not RDF, it is %s", qPrintable(root.tagName()));
return false;
}
QDomElement repo = root.firstChildElement("Repository");
//qDebug() << repo.attribute("resource");
for( QDomElement desc = repo.firstChildElement("Description");
!desc.isNull(); desc = desc.nextSiblingElement()) {
QString name = desc.firstChildElement("Name").text().toLower();
QString version = desc.firstChildElement("Version").text();
QString release = desc.firstChildElement("Release").text();
//qDebug() << desc.attribute("about");
RPMNode rpmnode;
if( nodes.contains(name)) rpmnode = nodes[name];
if( name.isEmpty() ) continue;
rpmnode.name = name;
rpmnode.about = desc.attribute("about");
rpmnode.version = version;
rpmnode.release = release;
for( QDomElement req = desc.firstChildElement("BuildPreReq");
!req.isNull(); req = req.nextSiblingElement("BuildPreReq")) {
if( req.hasAttribute("cond") ) continue;
QDomNodeList lst = req.elementsByTagName("resource");
for( int i = 0; i < lst.count(); ++i ) {
QString req = lst.item(i).toElement().text().toLower();
if( !req.isEmpty() && !req.contains("::") && req != rpmnode.name )
rpmnode.requires.insert( req );
}
}
for( QDomElement req = desc.firstChildElement("Provides");
!req.isNull(); req = req.nextSiblingElement("Provides")) {
QDomNodeList lst = req.elementsByTagName("resource");
for( int i = 0; i < lst.count(); ++i ) {
QString prov = lst.item(i).toElement().text().toLower();
if( !prov.isEmpty() )
rpmnode.provides.insert( prov );
}
}
rpmnode.provides.insert( rpmnode.name );
nodes[rpmnode.name] = rpmnode;
}
return true;
}
QStringList RPMSorter::sort() const
{
QMap<QString,RPMNode> nodes = this->nodes;
for( QMap<QString,RPMNode>::iterator it = nodes.begin();
it != nodes.end(); ++it ) {
if( (*it).requires.isEmpty() ) {
nodes[it.key()].requires.insert("START");
}
}
RPMNode startnode;
startnode.name="START";
nodes["START"] = startnode;
QStringList result;
while( !nodes.isEmpty() ) {
RPMNode current;
for( QMap<QString,RPMNode>::iterator it = nodes.begin();
it != nodes.end(); ++it ) {
//qDebug() << (*it).name << " has " << (*it).requires.count() << " deps";
if( (*it).requires.isEmpty() ) {
current = *it;
nodes.erase(it);
break;
}
}
if( current.name.isNull() ) {
std::cout << "Cycle detected. Remaining packages are" << std::endl;
dumpNodes(nodes);
qFatal("Bailing out!");
}
//qDebug() << qPrintable(current.name);
result << current.name;
for( QMap<QString,RPMNode>::iterator it = nodes.begin();
it != nodes.end(); ++it ) {
nodes[it.key()].requires.remove(current.name);
for( QSet<QString>::const_iterator it2 = current.provides.constBegin();
it2 != current.provides.constEnd(); ++it2 ) {
nodes[it.key()].requires.remove(*it2);
}
}
}
return result;
}
void RPMSorter::dumpNodes() const
{
dumpNodes(nodes);
}
void RPMSorter::dumpNodes( const QMap<QString,RPMNode>& nodes ) const
{
for( QMap<QString,RPMNode>::const_iterator it = nodes.constBegin();
it != nodes.constEnd(); ++it ) {
(*it).dumpNode();
}
}
int main( int argc, char** argv ) {
QCoreApplication app( argc, argv );
if( argc < 2 ) {
std::cout << "Usage: " << argv[0] << " file1.rdf [file2.rdf ...]" << std::endl;
exit(1);
}
RPMSorter sorter;
for( int i = 1; i < argc; ++i ) {
QFile file( argv[i] );
if (!file.open(QFile::ReadOnly | QFile::Text)) {
qFatal( qPrintable(file.errorString()));
}
sorter.addFrom(&file);
}
//sorter.dumpNodes();
std::cout << qPrintable( sorter.sort().join("\n") ) << std::endl;
return 0;
}
--- NEW FILE: rpmsort.pro ---
######################################################################
# Automatically generated by qmake (2.00a) Tue Jul 19 17:25:11 2005
######################################################################
QT += xml
CONFIG += warn_on debug
TEMPLATE = app
DEPENDPATH += .
INCLUDEPATH += .
# Input
SOURCES += main.cpp
More information about the commits
mailing list