KDevelop API Documentation

vcs/cvsservice/cvsfileinfoprovider.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 * Copyright (C) 2003 by Mario Scalas * 00003 * mario.scalas@libero.it * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation; either version 2 of the License, or * 00008 * (at your option) any later version. * 00009 * * 00010 ***************************************************************************/ 00011 00012 #include <qregexp.h> 00013 #include <kurl.h> 00014 #include <kdebug.h> 00015 00016 #include <urlutil.h> 00017 #include <kdevproject.h> 00018 00019 #include <dcopref.h> 00020 #include <cvsjob_stub.h> 00021 #include <cvsservice_stub.h> 00022 00023 #include "cvspart.h" 00024 #include "cvsdir.h" 00025 #include "cvsentry.h" 00026 #include "cvsfileinfoprovider.h" 00027 00028 00030 // class CVSFileInfoProvider 00032 00033 CVSFileInfoProvider::CVSFileInfoProvider( CvsServicePart *parent, CvsService_stub *cvsService ) 00034 : KDevVCSFileInfoProvider( parent, "cvsfileinfoprovider" ), 00035 m_requestStatusJob( 0 ), m_cvsService( cvsService ), m_cachedDirEntries( 0 ) 00036 { 00037 } 00038 00040 00041 CVSFileInfoProvider::~CVSFileInfoProvider() 00042 { 00043 if (m_requestStatusJob && m_requestStatusJob->isRunning()) 00044 m_requestStatusJob->cancel(); 00045 delete m_requestStatusJob; 00046 delete m_cachedDirEntries; 00047 } 00048 00050 00051 const VCSFileInfoMap *CVSFileInfoProvider::status( const QString &dirPath ) const 00052 { 00053 // Same dir: we can do with cache ... 00054 if (dirPath != m_previousDirPath) 00055 { 00056 // ... different dir: flush old cache and cache new dir 00057 delete m_cachedDirEntries; 00058 CVSDir cvsdir( projectDirectory() + QDir::separator() + dirPath ); 00059 m_previousDirPath = dirPath; 00060 m_cachedDirEntries = cvsdir.cacheableDirStatus(); 00061 } 00062 return m_cachedDirEntries; 00063 } 00064 00066 00067 bool CVSFileInfoProvider::requestStatus( const QString &dirPath, void *callerData ) 00068 { 00069 m_savedCallerData = callerData; 00070 if (m_requestStatusJob) 00071 { 00072 delete m_requestStatusJob; 00073 m_requestStatusJob = 0; 00074 } 00075 // Flush old cache 00076 if (m_cachedDirEntries) 00077 { 00078 delete m_cachedDirEntries; 00079 m_cachedDirEntries = 0; 00080 m_previousDirPath = dirPath; 00081 } 00082 00083 // path, recursive, tagInfo: hmmm ... we may use tagInfo for collecting file tags ... 00084 DCOPRef job = m_cvsService->status( dirPath, true, false ); 00085 m_requestStatusJob = new CvsJob_stub( job.app(), job.obj() ); 00086 00087 kdDebug(9006) << "Running command : " << m_requestStatusJob->cvsCommand() << endl; 00088 connectDCOPSignal( job.app(), job.obj(), "jobExited(bool, int)", "slotJobExited(bool, int)", true ); 00089 connectDCOPSignal( job.app(), job.obj(), "receivedStdout(QString)", "slotReceivedOutput(QString)", true ); 00090 return m_requestStatusJob->execute(); 00091 } 00092 00094 00095 void CVSFileInfoProvider::slotJobExited( bool normalExit, int /*exitStatus*/ ) 00096 { 00097 kdDebug(9006) << "CVSFileInfoProvider::slotJobExited(bool,int)" << endl; 00098 if (!normalExit) 00099 return; 00100 00101 // m_cachedDirEntries = parse( m_requestStatusJob->output() ); 00102 m_cachedDirEntries = parse( m_statusLines ); 00103 // Remove me when not debugging 00104 printOutFileInfoMap( *m_cachedDirEntries ); 00105 00106 emit statusReady( *m_cachedDirEntries, m_savedCallerData ); 00107 } 00108 00110 00111 void CVSFileInfoProvider::slotReceivedOutput( QString someOutput ) 00112 { 00113 QStringList strings = m_bufferedReader.process( someOutput ); 00114 if (strings.count() > 0) 00115 { 00116 m_statusLines += strings; 00117 } 00118 } 00119 00121 00122 void CVSFileInfoProvider::slotReceivedErrors( QString /*someErrors*/ ) 00123 { 00124 /* Nothing to do */ 00125 } 00126 00128 00129 QString CVSFileInfoProvider::projectDirectory() const 00130 { 00131 return owner()->project()->projectDirectory(); 00132 } 00133 00135 00136 VCSFileInfoMap *CVSFileInfoProvider::parse( QStringList stringStream ) 00137 { 00138 QRegExp rx_recordStart( "^=+$" ); 00139 QRegExp rx_fileName( "^File: (\\.|\\-|\\w)+" ); 00140 QRegExp rx_fileStatus( "Status: (\\.|-|\\s|\\w)+" ); 00141 QRegExp rx_fileWorkRev( "\\bWorking revision:" ); 00142 QRegExp rx_fileRepoRev( "\\bRepository revision:" ); 00143 //QRegExp rx_stickyTag( "\\s+(Sticky Tag:\\W+(w+|\\(none\\)))" ); 00144 //QRegExp rx_stickyDate( "" ); // @todo but are they useful?? :-/ 00145 //QRegExp rx_stickyOptions( "" ); //@todo 00146 00147 QString fileName, 00148 fileStatus, 00149 workingRevision, 00150 repositoryRevision, 00151 stickyTag, 00152 stickyDate, 00153 stickyOptions; 00154 00155 VCSFileInfoMap *vcsStates = new VCSFileInfoMap; 00156 00157 int state = 0; 00158 const int lastAcceptableState = 4; 00159 // This is where the dirty parsing is done: from a string stream representing the 00160 // 'cvs log' output we build a map with more useful strunctured data ;-) 00161 for (QStringList::const_iterator it=stringStream.begin(); it != stringStream.end(); ++it) 00162 { 00163 QString s = (*it).stripWhiteSpace(); 00164 kdDebug(9006) << ">> Parsing: " << s << endl; 00165 00166 if (rx_recordStart.exactMatch( s )) 00167 state = 1; 00168 else if (state == 1 && rx_fileName.search( s ) >= 0 && rx_fileStatus.search( s ) >= 0) // FileName 00169 { 00170 fileName = rx_fileName.cap().replace( "File:", "" ).stripWhiteSpace(); 00171 fileStatus = rx_fileStatus.cap().replace( "Status:", "" ).stripWhiteSpace(); 00172 ++state; // Next state 00173 kdDebug(9006) << ">> " << fileName << ", " << fileStatus << endl; 00174 } 00175 else if (state == 2 && rx_fileWorkRev.search( s ) >= 0) 00176 { 00177 workingRevision = s.replace( "Working revision:", "" ).stripWhiteSpace(); 00178 00179 QRegExp rx_revision( "\\b(((\\d)+\\.?)*|New file!)" ); 00180 if (rx_revision.search( workingRevision ) >= 0) 00181 { 00182 workingRevision = rx_revision.cap(); 00183 kdDebug(9006) << ">> WorkRev: " << workingRevision << endl; 00184 ++state; 00185 } 00186 } 00187 else if (state == 3 && rx_fileRepoRev.search( s ) >= 0) 00188 { 00189 repositoryRevision = s.replace( "Repository revision:", "" ).stripWhiteSpace(); 00190 00191 QRegExp rx_revision( "\\b(((\\d)+\\.?)*|No revision control file)" ); 00192 if (rx_revision.search( s ) >= 0) 00193 { 00194 repositoryRevision = rx_revision.cap(); 00195 kdDebug(9006) << ">> RepoRev: " << repositoryRevision << endl; 00196 ++state; 00197 } 00198 } 00199 /* 00200 else if (state == 4 && rx_stickyTag.search( s ) >= 0) 00201 { 00202 stickyTag = rx_stickyTag.cap(); 00203 ++state; 00204 } 00205 */ 00206 else if (state >= lastAcceptableState) // OK, parsed all useful info? 00207 { 00208 // Package stuff, put into map and get ready for a new record 00209 VCSFileInfo vcsInfo( fileName, workingRevision, repositoryRevision, 00210 String2EnumState( fileStatus ) ); 00211 kdDebug(9006) << "== Inserting: " << vcsInfo.toString() << endl; 00212 vcsStates->insert( fileName, vcsInfo ); 00213 } 00214 } 00215 return vcsStates; 00216 } 00217 00219 00220 VCSFileInfo::FileState CVSFileInfoProvider::String2EnumState( QString stateAsString ) 00221 { 00222 // @todo add more status as "Conflict" and "Sticky" (but I dunno how CVS writes it so I'm going 00223 // to await until I have a conflict or somebody else fix it ;-) 00224 // @todo use QRegExp for better matching since it seems strings have changed between CVS releases :-( 00225 // @todo a new state for 'Needs patch' 00226 if (stateAsString == "Up-to-date") 00227 return VCSFileInfo::Uptodate; 00228 else if (stateAsString == "Locally Modified") 00229 return VCSFileInfo::Modified; 00230 else if (stateAsString == "Locally Added") 00231 return VCSFileInfo::Added; 00232 else if (stateAsString == "Unresolved Conflict") 00233 return VCSFileInfo::Conflict; 00234 else if (stateAsString == "Needs Patch") 00235 return VCSFileInfo::NeedsPatch; 00236 else if (stateAsString == "Needs Checkout") 00237 return VCSFileInfo::NeedsCheckout; 00238 else 00239 return VCSFileInfo::Unknown; 00240 } 00241 00243 00244 void CVSFileInfoProvider::printOutFileInfoMap( const VCSFileInfoMap &map ) 00245 { 00246 kdDebug(9006) << "Files parsed:" << endl; 00247 for (VCSFileInfoMap::const_iterator it = map.begin(); it != map.end(); ++it) 00248 { 00249 const VCSFileInfo &vcsInfo = *it; 00250 kdDebug(9006) << vcsInfo.toString() << endl; 00251 } 00252 } 00253 00254 #include "cvsfileinfoprovider.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.0.4.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Oct 19 08:01:53 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003