SVN commit 614865 by hasso: As I got no objections and some users even tested it (I really appreciate this), I hope I'll not be killed because of committing this - subversion 1.4 support for catalogmanager. BUG:135795 CCMAIL:kde-i18n-doc@kde.org CCMAIL:kbabel@kde.org CCMAIL:kde-et@linux.ee M +104 -5 svnhandler.cpp M +23 -0 svnhandler.h --- branches/KDE/3.5/kdesdk/kbabel/catalogmanager/libsvn/svnhandler.cpp #614864:614865 @@ -50,10 +50,10 @@ #include #include #include +#include // project specific include files #include "svnhandler.h" - SVNHandler::SVNHandler( const QString& poBaseDir, const QString& potBaseDir ) { setPOBaseDir( poBaseDir ); @@ -126,19 +126,83 @@ QFileInfo info( fn ); - // check if '.svn/entries' exists and can be read + // check if '.svn/entries' exists. QFile entries( info.dir( true ).path( ) + "/.svn/entries" ); if ( !entries.exists() ) return NOT_IN_SVN; - - if ( !entries.open( IO_ReadOnly ) ) - return ERROR_IN_WC; // we already know that it is a repository + KProcess proc; + SVNOutputCollector out( &proc ); + + proc << "svn" << "status" << "-v" << "--xml" << info.absFilePath(); + + if( !proc.start( KProcess::Block, KProcess::Stdout ) ) + return ERROR_IN_WC; + QDomDocument doc; QString errorMsg; int errorLine, errorCol; + QDomNodeList nodelist; + QDomNode node; + QDomElement entry, wcStatus; + // Parse the output. + if ( !doc.setContent( out.output(), &errorMsg, &errorLine, &errorCol ) ) { + kdDebug(8109) << "Cannot parse \"svn status -v --xml\" output for" + << filename << endl << "Line: " << errorLine << " Column: " + << errorCol << " Error: " << errorMsg << endl; + goto no_status_xml; + } + + // There should be only one "entry" element. If it doesn't exist, path + // isn't repo path at all. + nodelist = doc.elementsByTagName("entry"); + if (nodelist.count() < 1) + return NOT_IN_SVN; + + entry = nodelist.item(0).toElement(); + + // Shouldn't fail, but just in case there is some weird error. + if ( entry.attributeNode("path").value() != info.absFilePath() ) + return ERROR_IN_WC; + + for ( node = entry.firstChild(); !node.isNull(); node = node.nextSibling() ) { + if ( !node.isElement() ) + continue; + if (node.toElement().tagName() == "wc-status") + break; + } + + if ( node.isNull() ) + return ERROR_IN_WC; + + wcStatus = node.toElement(); + + if ( wcStatus.attributeNode("item").value() == "normal" ) + return UP_TO_DATE; + if ( wcStatus.attributeNode("item").value() == "modified" ) + return LOCALLY_MODIFIED; + if ( wcStatus.attributeNode("item").value() == "conflicted" ) + return CONFLICT; + if ( wcStatus.attributeNode("item").value() == "unversioned" ) + return NOT_IN_SVN; + // TODO Ignored entry should have separate return value probably. + if ( wcStatus.attributeNode("item").value() == "ignored" ) + return NOT_IN_SVN; + if ( wcStatus.attributeNode("item").value() == "added" ) + return LOCALLY_ADDED; + if ( wcStatus.attributeNode("item").value() == "deleted" ) + return LOCALLY_REMOVED; + // TODO What to do with "missing", "incomplete", "replaced", "merged", + // "obstructed", "external"? Can these appear at all in our case? + + return ERROR_IN_WC; + +no_status_xml: + if ( !entries.open( IO_ReadOnly ) ) + return ERROR_IN_WC; // we already know that it is a repository + // Parse the entries file if ( !doc.setContent( &entries, &errorMsg, &errorLine, &errorCol ) ) { kdDebug() << "Cannot parse .svn/entries file for " << filename << endl @@ -439,7 +503,42 @@ return status == LOCALLY_MODIFIED || status == NOT_IN_SVN; } +SVNOutputCollector::SVNOutputCollector( KProcess* p ) + : m_process(0) +{ + setProcess( p ); +} +void SVNOutputCollector::setProcess( KProcess* p ) +{ + if( m_process ) + m_process->disconnect( this ); + + m_process = p; + if( p ) { + connect( p, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotGatherStdout(KProcess*, char*, int)) ); + connect( p, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotGatherStderr(KProcess*, char*, int)) ); + } + + m_gatheredOutput.truncate( 0 ); + m_stderrOutput.truncate( 0 ); + m_stdoutOutput.truncate( 0 ); +} + +void SVNOutputCollector::slotGatherStderr( KProcess*, char* data, int len ) +{ + m_gatheredOutput.append( QString::fromLocal8Bit( data, len ) ); + m_stderrOutput.append( QString::fromLocal8Bit( data, len ) ); +} + +void SVNOutputCollector::slotGatherStdout( KProcess*, char* data, int len ) +{ + m_gatheredOutput.append( QString::fromLocal8Bit( data, len ) ); + m_stdoutOutput.append( QString::fromLocal8Bit( data, len ) ); +} + #include "svnhandler.moc" // kate: space-indent on; indent-width 2; replace-tabs on; --- branches/KDE/3.5/kdesdk/kbabel/catalogmanager/libsvn/svnhandler.h #614864:614865 @@ -112,4 +112,27 @@ QMap map; }; +class SVNOutputCollector: public QObject +{ + Q_OBJECT + + public: + SVNOutputCollector( KProcess* ); + void setProcess( KProcess* ); + + const QString& output() const { return m_gatheredOutput; } + const QString& stderr() const { return m_stderrOutput; } + const QString& stdout() const { return m_stdoutOutput; } + + private slots: + void slotGatherStderr( KProcess*, char*, int ); + void slotGatherStdout( KProcess*, char*, int ); + + private: + QString m_gatheredOutput; + QString m_stderrOutput; + QString m_stdoutOutput; + KProcess* m_process; +}; + #endif // SVNHANDLER_H