Sophie

Sophie

distrib > Mandriva > 2009.0 > x86_64 > media > main-testing-src > by-pkgid > 69501fee79f575b9818fcbd4bf2bb6c4 > files > 17

kdelibs4-4.2.4-0.2mdv2009.0.src.rpm

Index: kio/kio/copyjob.cpp
===================================================================
--- kio/kio/copyjob.cpp (revision 956991)
+++ kio/kio/copyjob.cpp (working copy)
@@ -20,6 +20,8 @@
 */
 
 #include "copyjob.h"
+#include "kdirlister.h"
+#include "kfileitem.h"
 #include "deletejob.h"
 
 #include <klocale.h>
@@ -160,7 +162,7 @@
     bool m_bSingleFileCopy;
     bool m_bOnlyRenames;
     KUrl m_dest;
-    KUrl m_currentDest;
+    KUrl m_currentDest; // set during listing, used by slotEntries
     //
     QStringList m_skipList;
     QStringList m_overwriteList;
@@ -191,6 +193,7 @@
     void copyNextFile();
     void slotResultDeletingDirs( KJob * job );
     void deleteNextDir();
+    void sourceStated(const UDSEntry& entry, const KUrl& sourceUrl);
     void skip( const KUrl & sourceURL );
     void slotResultRenaming( KJob * job );
     void slotResultSettingDirAttributes( KJob * job );
@@ -204,6 +207,7 @@
 
     void slotStart();
     void slotEntries( KIO::Job*, const KIO::UDSEntryList& list );
+    void addCopyInfoFromUDSEntry(const UDSEntry& entry, const KUrl& srcUrl, bool srcIsDir, const KUrl& currentDest);
     /**
      * Forward signal from subjob
      */
@@ -264,7 +268,7 @@
 
     // Stat the dest
     KIO::Job * job = KIO::stat( m_dest, StatJob::DestinationSide, 2, KIO::HideProgressInfo );
-    //kDebug(7007) << "CopyJob:stating the dest " << d->m_dest;
+    //kDebug(7007) << "CopyJob:stating the dest " << m_dest;
     q->addSubjob(job);
 }
 
@@ -278,7 +282,7 @@
     // Was there an error while stating the src ?
     if (job->error() && destinationState != DEST_NOT_STATED )
     {
-        KUrl srcurl = ((SimpleJob*)job)->url();
+        const KUrl srcurl = static_cast<SimpleJob*>(job)->url();
         if ( !srcurl.isLocalFile() )
         {
             // Probably : src doesn't exist. Well, over some protocols (e.g. FTP)
@@ -310,23 +314,22 @@
 
     // Keep copy of the stat result
     const UDSEntry entry = static_cast<StatJob*>(job)->statResult();
-    const QString sLocalPath = entry.stringValue( KIO::UDSEntry::UDS_LOCAL_PATH );
-    const bool isDir = entry.isDir();
 
-    if ( destinationState == DEST_NOT_STATED )
+    if ( destinationState == DEST_NOT_STATED ) {
+        const bool isDir = entry.isDir();
         // we were stating the dest
-    {
         if (job->error())
             destinationState = DEST_DOESNT_EXIST;
         else {
             // Treat symlinks to dirs as dirs here, so no test on isLink
             destinationState = isDir ? DEST_IS_DIR : DEST_IS_FILE;
-            //kDebug(7007) << "dest is dir:" << bDir;
+            //kDebug(7007) << "dest is dir:" << isDir;
         }
         const bool isGlobalDest = m_dest == m_globalDest;
         if ( isGlobalDest )
             m_globalDestinationState = destinationState;
 
+        const QString sLocalPath = entry.stringValue( KIO::UDSEntry::UDS_LOCAL_PATH );
         if ( !sLocalPath.isEmpty() && kio_resolve_local_urls ) {
             m_dest = KUrl();
             m_dest.setPath(sLocalPath);
@@ -339,19 +342,21 @@
 
         // After knowing what the dest is, we can start stat'ing the first src.
         statCurrentSrc();
-        return;
+    } else {
+        sourceStated(entry, static_cast<SimpleJob*>(job)->url());
+        q->removeSubjob( job );
     }
+}
 
-    // Is it a file or a dir ?
-    const QString sName = entry.stringValue( KIO::UDSEntry::UDS_NAME );
+void CopyJobPrivate::sourceStated(const UDSEntry& entry, const KUrl& sourceUrl)
+{
+    const QString sLocalPath = entry.stringValue( KIO::UDSEntry::UDS_LOCAL_PATH );
+    const bool isDir = entry.isDir();
 
     // We were stating the current source URL
-    m_currentDest = m_dest; // used by slotEntries
-    // Create a dummy list with it, for slotEntries
-    UDSEntryList lst;
-    lst.append(entry);
+    // Is it a file or a dir ?
 
-    // There 6 cases, and all end up calling slotEntries(job, lst) first :
+    // There 6 cases, and all end up calling addCopyInfoFromUDSEntry first :
     // 1 - src is a dir, destination is a directory,
     // slotEntries will append the source-dir-name to the destination
     // 2 - src is a dir, destination is a file -- will offer to overwrite, later on.
@@ -362,18 +367,16 @@
     // slotEntries will append the filename to the destination.
     // 5 - src is a file, destination is a file, m_dest is the exact destination name
     // 6 - src is a file, destination doesn't exist, m_dest is the exact destination name
-    // Tell slotEntries not to alter the src url
-    m_bCurrentSrcIsDir = false;
-    slotEntries(static_cast<KIO::Job*>( job ), lst);
 
     KUrl srcurl;
     if (!sLocalPath.isEmpty())
         srcurl.setPath(sLocalPath);
     else
-        srcurl = ((SimpleJob*)job)->url();
+        srcurl = sourceUrl;
+    addCopyInfoFromUDSEntry(entry, srcurl, false, m_dest);
 
-    q->removeSubjob( job );
-    assert ( !q->hasSubjobs() ); // We should have only one job at a time ...
+    m_currentDest = m_dest;
+    m_bCurrentSrcIsDir = false;
 
     if ( isDir
          // treat symlinks as files (no recursion)
@@ -389,8 +392,8 @@
             {
                 // Use <desturl>/<directory_copied> as destination, from now on
                 QString directory = srcurl.fileName();
-                if ( !sName.isEmpty() && KProtocolManager::fileNameUsedForCopying( srcurl ) == KProtocolInfo::Name )
-                {
+                const QString sName = entry.stringValue( KIO::UDSEntry::UDS_NAME );
+                if (!sName.isEmpty() && KProtocolManager::fileNameUsedForCopying(srcurl) == KProtocolInfo::Name) {
                     directory = sName;
                 }
                 m_currentDest.addPath( directory );
@@ -498,67 +501,71 @@
     UDSEntryList::ConstIterator end = list.constEnd();
     for (; it != end; ++it) {
         const UDSEntry& entry = *it;
+        addCopyInfoFromUDSEntry(entry, static_cast<SimpleJob *>(job)->url(), m_bCurrentSrcIsDir, m_currentDest);
+    }
+}
+
+void CopyJobPrivate::addCopyInfoFromUDSEntry(const UDSEntry& entry, const KUrl& srcUrl, bool srcIsDir, const KUrl& currentDest)
+{
         struct CopyInfo info;
-        info.permissions = entry.numberValue( KIO::UDSEntry::UDS_ACCESS, -1 );
-        info.mtime = (time_t) entry.numberValue( KIO::UDSEntry::UDS_MODIFICATION_TIME, -1 );
-        info.ctime = (time_t) entry.numberValue( KIO::UDSEntry::UDS_CREATION_TIME, -1 );
-        info.size = (KIO::filesize_t) entry.numberValue( KIO::UDSEntry::UDS_SIZE, -1 );
-        if ( info.size != (KIO::filesize_t) -1 )
+    info.permissions = entry.numberValue(KIO::UDSEntry::UDS_ACCESS, -1);
+    info.mtime = (time_t) entry.numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME, -1);
+    info.ctime = (time_t) entry.numberValue(KIO::UDSEntry::UDS_CREATION_TIME, -1);
+    info.size = (KIO::filesize_t) entry.numberValue(KIO::UDSEntry::UDS_SIZE, -1);
+    if (info.size != (KIO::filesize_t) -1)
             m_totalSize += info.size;
 
         // recursive listing, displayName can be a/b/c/d
-        const QString displayName = entry.stringValue( KIO::UDSEntry::UDS_NAME );
-        const QString urlStr = entry.stringValue( KIO::UDSEntry::UDS_URL );
+    const QString displayName = entry.stringValue(KIO::UDSEntry::UDS_NAME);
+    const QString urlStr = entry.stringValue(KIO::UDSEntry::UDS_URL);
         KUrl url;
-        if ( !urlStr.isEmpty() )
+    if (!urlStr.isEmpty())
             url = urlStr;
-        QString localPath = entry.stringValue( KIO::UDSEntry::UDS_LOCAL_PATH );
+    QString localPath = entry.stringValue(KIO::UDSEntry::UDS_LOCAL_PATH);
         const bool isDir = entry.isDir();
-        info.linkDest = entry.stringValue( KIO::UDSEntry::UDS_LINK_DEST );
+    info.linkDest = entry.stringValue(KIO::UDSEntry::UDS_LINK_DEST);
 
-        if (displayName != ".." && displayName != ".")
-        {
-            bool hasCustomURL = !url.isEmpty() || !localPath.isEmpty();
-            if( !hasCustomURL ) {
+    if (displayName != QLatin1String("..") && displayName != QLatin1String(".")) {
+        const bool hasCustomURL = !url.isEmpty() || !localPath.isEmpty();
+        if (!hasCustomURL) {
                 // Make URL from displayName
-                url = static_cast<SimpleJob *>(job)->url();
-                if ( m_bCurrentSrcIsDir ) { // Only if src is a directory. Otherwise uSource is fine as is
-                    //kDebug(7007) << "adding path " << displayName;
-                    url.addPath( displayName );
+            url = srcUrl;
+            if (srcIsDir) { // Only if src is a directory. Otherwise uSource is fine as is
+                //kDebug(7007) << "adding path" << displayName;
+                url.addPath(displayName);
                 }
             }
             //kDebug(7007) << "displayName=" << displayName << "url=" << url;
             if (!localPath.isEmpty() && kio_resolve_local_urls) {
-                url = KUrl();
-                url.setPath(localPath);
+            url = KUrl(localPath);
             }
 
             info.uSource = url;
-            info.uDest = m_currentDest;
+        info.uDest = currentDest;
             //kDebug(7007) << "uSource=" << info.uSource << "uDest(1)=" << info.uDest;
             // Append filename or dirname to destination URL, if allowed
-            if ( destinationState == DEST_IS_DIR &&
+        if (destinationState == DEST_IS_DIR &&
                  // "copy/move as <foo>" means 'foo' is the dest for the base srcurl
                  // (passed here during stating) but not its children (during listing)
-                 ( ! ( m_asMethod && state == STATE_STATING ) ) )
+             (! (m_asMethod && state == STATE_STATING)))
             {
                 QString destFileName;
-                if ( hasCustomURL &&
-                     KProtocolManager::fileNameUsedForCopying( url ) == KProtocolInfo::FromUrl ) {
+            if (hasCustomURL &&
+                 KProtocolManager::fileNameUsedForCopying(url) == KProtocolInfo::FromUrl) {
                     //destFileName = url.fileName(); // Doesn't work for recursive listing
                     // Count the number of prefixes used by the recursive listjob
-                    int numberOfSlashes = displayName.count( '/' ); // don't make this a find()!
+                int numberOfSlashes = displayName.count('/'); // don't make this a find()!
                     QString path = url.path();
                     int pos = 0;
-                    for ( int n = 0; n < numberOfSlashes + 1; ++n ) {
-                        pos = path.lastIndexOf( '/', pos - 1 );
-                        if ( pos == -1 ) { // error
+                for (int n = 0; n < numberOfSlashes + 1; ++n) {
+                    pos = path.lastIndexOf('/', pos - 1);
+                    if (pos == -1) { // error
                             kWarning(7007) << "kioslave bug: not enough slashes in UDS_URL" << path << "- looking for" << numberOfSlashes << "slashes";
                             break;
                         }
                     }
-                    if ( pos >= 0 ) {
-                        destFileName = path.mid( pos + 1 );
+                if (pos >= 0) {
+                    destFileName = path.mid(pos + 1);
                     }
 
                 } else { // destination filename taken from UDS_NAME
@@ -568,23 +575,22 @@
                 // Here we _really_ have to add some filename to the dest.
                 // Otherwise, we end up with e.g. dest=..../Desktop/ itself.
                 // (This can happen when dropping a link to a webpage with no path)
-                if ( destFileName.isEmpty() )
-                    destFileName = KIO::encodeFileName( info.uSource.prettyUrl() );
+            if (destFileName.isEmpty()) {
+                destFileName = KIO::encodeFileName(info.uSource.prettyUrl());
+            }
 
                 //kDebug(7007) << " adding destFileName=" << destFileName;
-                info.uDest.addPath( destFileName );
+            info.uDest.addPath(destFileName);
             }
             //kDebug(7007) << " uDest(2)=" << info.uDest;
             //kDebug(7007) << " " << info.uSource << "->" << info.uDest;
-            if ( info.linkDest.isEmpty() && isDir && m_mode != CopyJob::Link ) // Dir
-            {
-                dirs.append( info ); // Directories
-                if (m_mode == CopyJob::Move)
-                    dirsToRemove.append( info.uSource );
+        if (info.linkDest.isEmpty() && isDir && m_mode != CopyJob::Link) { // Dir
+            dirs.append(info); // Directories
+            if (m_mode == CopyJob::Move) {
+                dirsToRemove.append(info.uSource);
             }
-            else {
-                files.append( info ); // Files and any symlinks
-            }
+        } else {
+            files.append(info); // Files and any symlinks
         }
     }
 }
@@ -613,12 +619,10 @@
 void CopyJobPrivate::statCurrentSrc()
 {
     Q_Q(CopyJob);
-    if ( m_currentStatSrc != m_srcList.constEnd() )
-    {
+    if (m_currentStatSrc != m_srcList.constEnd()) {
         m_currentSrcURL = (*m_currentStatSrc);
         m_bURLDirty = true;
-        if ( m_mode == CopyJob::Link )
-        {
+        if (m_mode == CopyJob::Link) {
             // Skip the "stating the source" stage, we don't need it for linking
             m_currentDest = m_dest;
             struct CopyInfo info;
@@ -629,36 +633,41 @@
             info.uSource = m_currentSrcURL;
             info.uDest = m_currentDest;
             // Append filename or dirname to destination URL, if allowed
-            if ( destinationState == DEST_IS_DIR && !m_asMethod )
-            {
+            if (destinationState == DEST_IS_DIR && !m_asMethod) {
                 if (
                     (m_currentSrcURL.protocol() == info.uDest.protocol()) &&
                     (m_currentSrcURL.host() == info.uDest.host()) &&
                     (m_currentSrcURL.port() == info.uDest.port()) &&
                     (m_currentSrcURL.user() == info.uDest.user()) &&
-                    (m_currentSrcURL.pass() == info.uDest.pass()) )
-                {
+                    (m_currentSrcURL.pass() == info.uDest.pass()) ) {
                     // This is the case of creating a real symlink
                     info.uDest.addPath( m_currentSrcURL.fileName() );
-                }
-                else
-                {
+                } else {
                     // Different protocols, we'll create a .desktop file
                     // We have to change the extension anyway, so while we're at it,
                     // name the file like the URL
-                    info.uDest.addPath( KIO::encodeFileName( m_currentSrcURL.prettyUrl() )+".desktop" );
+                    info.uDest.addPath(KIO::encodeFileName(m_currentSrcURL.prettyUrl()) + ".desktop");
                 }
             }
             files.append( info ); // Files and any symlinks
             statNextSrc(); // we could use a loop instead of a recursive call :)
             return;
         }
-        else if ( m_mode == CopyJob::Move && (
+
+        // Let's see if we can skip stat'ing, for the case where a directory view has the info already
+        const KFileItem cachedItem = KDirLister::cachedItemForUrl(m_currentSrcURL);
+        KIO::UDSEntry entry;
+        if (!cachedItem.isNull()) {
+            entry = cachedItem.entry();
+            bool dummyIsLocal;
+            m_currentSrcURL = cachedItem.mostLocalUrl(dummyIsLocal); // #183585
+        }
+
+        if (m_mode == CopyJob::Move && (
                 // Don't go renaming right away if we need a stat() to find out the destination filename
-                KProtocolManager::fileNameUsedForCopying( m_currentSrcURL ) == KProtocolInfo::FromUrl ||
-                destinationState != DEST_IS_DIR || m_asMethod )
-            )
-        {
+                KProtocolManager::fileNameUsedForCopying(m_currentSrcURL) == KProtocolInfo::FromUrl ||
+                destinationState != DEST_IS_DIR || m_asMethod)
+            ) {
            // If moving, before going for the full stat+[list+]copy+del thing, try to rename
            // The logic is pretty similar to FileCopyJobPrivate::slotStart()
            if ( (m_currentSrcURL.protocol() == m_dest.protocol()) &&
@@ -691,13 +700,20 @@
             return;
         }
 
+        m_bOnlyRenames = false;
+
+        if (entry.count() > 0) {
+            kDebug(7007) << "fast path! found info about" << m_currentSrcURL << "in KDirLister";
+            sourceStated(entry, m_currentSrcURL);
+            return;
+        }
+
         // Stat the next src url
         Job * job = KIO::stat( m_currentSrcURL, StatJob::SourceSide, 2, KIO::HideProgressInfo );
-        //kDebug(7007) << "KIO::stat on " << m_currentSrcURL;
+        //kDebug(7007) << "KIO::stat on" << m_currentSrcURL;
         state = STATE_STATING;
         q->addSubjob(job);
-        m_currentDestURL=m_dest;
-        m_bOnlyRenames = false;
+        m_currentDestURL = m_dest;
         m_bURLDirty = true;
     }
     else
@@ -1521,7 +1537,7 @@
         KUrl url(d->m_globalDest);
         if (d->m_globalDestinationState != DEST_IS_DIR || d->m_asMethod)
             url.setPath(url.directory());
-        //kDebug(7007) << "KDirNotify'ing FilesAdded " << url;
+        //kDebug(7007) << "KDirNotify'ing FilesAdded" << url;
         org::kde::KDirNotify::emitFilesAdded( url.url() );
 
         if (d->m_mode == CopyJob::Move && !d->m_successSrcList.isEmpty()) {
@@ -1543,24 +1559,24 @@
   {
     // Example: download any attachment from bugs.kde.org
     m_totalSize = m_processedSize + m_fileProcessedSize;
-    //kDebug(7007) << "Adjusting m_totalSize to " << m_totalSize;
+    //kDebug(7007) << "Adjusting m_totalSize to" << m_totalSize;
     q->setTotalAmount(KJob::Bytes, m_totalSize); // safety
   }
-  //kDebug(7007) << "emit processedSize " << (unsigned long) (m_processedSize + m_fileProcessedSize);
+  //kDebug(7007) << "emit processedSize" << (unsigned long) (m_processedSize + m_fileProcessedSize);
   q->setProcessedAmount(KJob::Bytes, m_processedSize + m_fileProcessedSize);
 }
 
 void CopyJobPrivate::slotTotalSize( KJob*, qulonglong size )
 {
   Q_Q(CopyJob);
-  //kDebug(7007) << "slotTotalSize: " << size;
+  //kDebug(7007) << size;
   // Special case for copying a single file
   // This is because some protocols don't implement stat properly
   // (e.g. HTTP), and don't give us a size in some cases (redirection)
   // so we'd rather rely on the size given for the transfer
   if ( m_bSingleFileCopy && size > m_totalSize)
   {
-    //kDebug(7007) << "slotTotalSize: updating totalsize to " << size;
+    //kDebug(7007) << "slotTotalSize: updating totalsize to" << size;
     m_totalSize = size;
     q->setTotalAmount(KJob::Bytes, size);
   }
@@ -1791,7 +1807,7 @@
             return;
         }
         kDebug(7007) << "Couldn't rename" << m_currentSrcURL << "to" << dest << ", reverting to normal way, starting with stat";
-        //kDebug(7007) << "KIO::stat on " << m_currentSrcURL;
+        //kDebug(7007) << "KIO::stat on" << m_currentSrcURL;
         KIO::Job* job = KIO::stat( m_currentSrcURL, StatJob::SourceSide, 2, KIO::HideProgressInfo );
         state = STATE_STATING;
         q->addSubjob(job);