Ignore:
Timestamp:
Jan 9, 2017, 11:09:38 AM (3 years ago)
Author:
jrpelegrina
Message:

Update new version: 3.15.02

File:
1 edited

Legend:

Unmodified
Added
Removed
  • filezilla/trunk/fuentes/src/interface/recursive_operation.cpp

    r130 r3185  
    66#include "Options.h"
    77#include "queue.h"
    8 #include "local_filesys.h"
    9 
    10 CRecursiveOperation::CRecursiveOperation(CState* pState)
    11         : CStateEventHandler(pState),
    12           m_operationMode(recursive_none)
    13 {
    14         pState->RegisterHandler(this, STATECHANGE_REMOTE_DIR_OTHER);
    15         pState->RegisterHandler(this, STATECHANGE_REMOTE_LINKNOTDIR);
    16 }
    17 
    18 CRecursiveOperation::~CRecursiveOperation()
    19 {
    20         if (m_pChmodDlg)
    21         {
    22                 m_pChmodDlg->Destroy();
    23                 m_pChmodDlg = 0;
    24         }
    25 }
    26 
    27 void CRecursiveOperation::OnStateChange(CState* pState, enum t_statechange_notifications notification, const wxString&, const void* data2)
    28 {
    29         if (notification == STATECHANGE_REMOTE_DIR_OTHER && data2) {
    30                 std::shared_ptr<CDirectoryListing> const& listing = *reinterpret_cast<std::shared_ptr<CDirectoryListing> const*>(data2);
    31                 ProcessDirectoryListing(listing.get());
    32         }
    33         else if (notification == STATECHANGE_REMOTE_LINKNOTDIR) {
    34                 wxASSERT(data2);
    35                 LinkIsNotDir();
    36         }
    37 }
    38 
    39 void CRecursiveOperation::StartRecursiveOperation(OperationMode mode, const CServerPath& startDir, std::vector<CFilter> const& filters, bool allowParent /*=false*/, const CServerPath& finalDir /*=CServerPath()*/)
    40 {
    41         wxCHECK_RET(m_operationMode == recursive_none, _T("StartRecursiveOperation called with m_operationMode != recursive_none"));
    42         wxCHECK_RET(m_pState->IsRemoteConnected(), _T("StartRecursiveOperation while disconnected"));
    43         wxCHECK_RET(!startDir.empty(), _T("Empty startDir in StartRecursiveOperation"));
    44 
    45         if (mode == recursive_chmod && !m_pChmodDlg)
    46                 return;
    47 
    48         if ((mode == recursive_download || mode == recursive_addtoqueue || mode == recursive_download_flatten || mode == recursive_addtoqueue_flatten) && !m_pQueue)
    49                 return;
    50 
    51         if (m_dirsToVisit.empty()) {
    52                 // Nothing to do in this case
    53                 return;
    54         }
    55 
    56         m_processedFiles = 0;
    57         m_processedDirectories = 0;
    58 
    59         m_operationMode = mode;
    60         m_pState->NotifyHandlers(STATECHANGE_REMOTE_IDLE);
    61         m_pState->NotifyHandlers(STATECHANGE_RECURSION_STATUS);
    62 
    63         m_startDir = startDir;
    64 
    65         if (finalDir.empty())
    66                 m_finalDir = startDir;
    67         else
    68                 m_finalDir = finalDir;
    69 
    70         m_allowParent = allowParent;
    71 
    72         m_filters = filters;
    73 
    74         NextOperation();
    75 }
    76 
    77 void CRecursiveOperation::AddDirectoryToVisit(const CServerPath& path, const wxString& subdir, const CLocalPath& localDir /*=CLocalPath()*/, bool is_link /*=false*/)
    78 {
    79         CNewDir dirToVisit;
     8
     9recursion_root::recursion_root(CServerPath const& start_dir, bool allow_parent)
     10        : m_startDir(start_dir)
     11        , m_allowParent(allow_parent)
     12{
     13        wxASSERT_MSG(!start_dir.empty(), _T("Empty startDir in recursion_root constructor"));
     14}
     15
     16void recursion_root::add_dir_to_visit(CServerPath const& path, wxString const& subdir, CLocalPath const& localDir, bool is_link)
     17{
     18        new_dir dirToVisit;
    8019
    8120        dirToVisit.localDir = localDir;
     
    8625}
    8726
    88 void CRecursiveOperation::AddDirectoryToVisitRestricted(const CServerPath& path, const wxString& restrict, bool recurse)
    89 {
    90         CNewDir dirToVisit;
     27void recursion_root::add_dir_to_visit_restricted(CServerPath const& path, wxString const& restrict, bool recurse)
     28{
     29        new_dir dirToVisit;
    9130        dirToVisit.parent = path;
    9231        dirToVisit.recurse = recurse;
    93         dirToVisit.restrict = restrict;
     32        if (!restrict.empty()) {
     33                dirToVisit.restrict = CSparseOptional<wxString>(restrict);
     34        }
    9435        m_dirsToVisit.push_back(dirToVisit);
     36}
     37
     38
     39
     40CRecursiveOperation::CRecursiveOperation(CState* pState)
     41        : CStateEventHandler(pState),
     42          m_operationMode(recursive_none)
     43{
     44        pState->RegisterHandler(this, STATECHANGE_REMOTE_DIR_OTHER);
     45        pState->RegisterHandler(this, STATECHANGE_REMOTE_LINKNOTDIR);
     46}
     47
     48CRecursiveOperation::~CRecursiveOperation()
     49{
     50        if (m_pChmodDlg)
     51        {
     52                m_pChmodDlg->Destroy();
     53                m_pChmodDlg = 0;
     54        }
     55}
     56
     57void CRecursiveOperation::OnStateChange(CState*, enum t_statechange_notifications notification, const wxString&, const void* data2)
     58{
     59        if (notification == STATECHANGE_REMOTE_DIR_OTHER && data2) {
     60                std::shared_ptr<CDirectoryListing> const& listing = *reinterpret_cast<std::shared_ptr<CDirectoryListing> const*>(data2);
     61                ProcessDirectoryListing(listing.get());
     62        }
     63        else if (notification == STATECHANGE_REMOTE_LINKNOTDIR) {
     64                wxASSERT(data2);
     65                LinkIsNotDir();
     66        }
     67}
     68
     69void CRecursiveOperation::AddRecursionRoot(recursion_root && root)
     70{
     71        if (!root.empty()) {
     72                recursion_roots_.push_back(std::forward<recursion_root>(root));
     73        }
     74}
     75
     76void CRecursiveOperation::StartRecursiveOperation(OperationMode mode, std::vector<CFilter> const& filters, CServerPath const& finalDir)
     77{
     78        wxCHECK_RET(m_operationMode == recursive_none, _T("StartRecursiveOperation called with m_operationMode != recursive_none"));
     79        wxCHECK_RET(m_pState->IsRemoteConnected(), _T("StartRecursiveOperation while disconnected"));
     80        wxCHECK_RET(!finalDir.empty(), _T("Empty final dir in recursive operation"));
     81
     82        if (mode == recursive_chmod && !m_pChmodDlg)
     83                return;
     84
     85        if ((mode == recursive_download || mode == recursive_addtoqueue || mode == recursive_download_flatten || mode == recursive_addtoqueue_flatten) && !m_pQueue)
     86                return;
     87
     88        if (recursion_roots_.empty()) {
     89                // Nothing to do in this case
     90                return;
     91        }
     92
     93        m_processedFiles = 0;
     94        m_processedDirectories = 0;
     95
     96        m_operationMode = mode;
     97        m_pState->NotifyHandlers(STATECHANGE_REMOTE_IDLE);
     98        m_pState->NotifyHandlers(STATECHANGE_RECURSION_STATUS);
     99
     100        m_filters = filters;
     101
     102        NextOperation();
    95103}
    96104
     
    100108                return false;
    101109
    102         while (!m_dirsToVisit.empty()) {
    103                 const CNewDir& dirToVisit = m_dirsToVisit.front();
    104                 if (m_operationMode == recursive_delete && !dirToVisit.doVisit) {
    105                         m_pState->m_pCommandQueue->ProcessCommand(new CRemoveDirCommand(dirToVisit.parent, dirToVisit.subdir), CCommandQueue::recursiveOperation);
    106                         m_dirsToVisit.pop_front();
    107                         continue;
    108                 }
    109 
    110                 CListCommand* cmd = new CListCommand(dirToVisit.parent, dirToVisit.subdir, dirToVisit.link ? LIST_FLAG_LINK : 0);
    111                 m_pState->m_pCommandQueue->ProcessCommand(cmd, CCommandQueue::recursiveOperation);
    112                 return true;
     110        while (!recursion_roots_.empty()) {
     111                auto & root = recursion_roots_.front();
     112                while (!root.m_dirsToVisit.empty()) {
     113                        const recursion_root::new_dir& dirToVisit = root.m_dirsToVisit.front();
     114                        if (m_operationMode == recursive_delete && !dirToVisit.doVisit) {
     115                                m_pState->m_pCommandQueue->ProcessCommand(new CRemoveDirCommand(dirToVisit.parent, dirToVisit.subdir), CCommandQueue::recursiveOperation);
     116                                root.m_dirsToVisit.pop_front();
     117                                continue;
     118                        }
     119
     120                        CListCommand* cmd = new CListCommand(dirToVisit.parent, dirToVisit.subdir, dirToVisit.link ? LIST_FLAG_LINK : 0);
     121                        m_pState->m_pCommandQueue->ProcessCommand(cmd, CCommandQueue::recursiveOperation);
     122                        return true;
     123                }
     124
     125                recursion_roots_.pop_front();
    113126        }
    114127
     
    128141}
    129142
    130 bool CRecursiveOperation::BelowRecursionRoot(const CServerPath& path, CNewDir &dir)
     143bool CRecursiveOperation::BelowRecursionRoot(const CServerPath& path, recursion_root::new_dir &dir)
    131144{
    132145        if (!dir.start_dir.empty()) {
     
    137150        }
    138151
    139         if (path.IsSubdirOf(m_startDir, false))
     152        auto & root = recursion_roots_.front();
     153        if (path.IsSubdirOf(root.m_startDir, false))
    140154                return true;
    141155
    142156        // In some cases (chmod from tree for example) it is neccessary to list the
    143157        // parent first
    144         if (path == m_startDir && m_allowParent)
     158        if (path == root.m_startDir && root.m_allowParent)
    145159                return true;
    146160
     
    163177        }
    164178
    165         if (m_operationMode == recursive_none)
     179        if (m_operationMode == recursive_none || recursion_roots_.empty())
    166180                return;
    167181
     
    172186        }
    173187
    174         wxASSERT(!m_dirsToVisit.empty());
    175 
    176         if (!m_pState->IsRemoteConnected() || m_dirsToVisit.empty()) {
     188        auto & root = recursion_roots_.front();
     189        wxASSERT(!root.m_dirsToVisit.empty());
     190
     191        if (!m_pState->IsRemoteConnected() || root.m_dirsToVisit.empty()) {
    177192                StopRecursiveOperation();
    178193                return;
    179194        }
    180195
    181         CNewDir dir = m_dirsToVisit.front();
    182         m_dirsToVisit.pop_front();
     196        recursion_root::new_dir dir = root.m_dirsToVisit.front();
     197        root.m_dirsToVisit.pop_front();
    183198
    184199        if (!BelowRecursionRoot(pDirectoryListing->path, dir)) {
     
    190205                // After recursing into directory to delete its contents, delete directory itself
    191206                // Gets handled in NextOperation
    192                 CNewDir dir2 = dir;
     207                recursion_root::new_dir dir2 = dir;
    193208                dir2.doVisit = false;
    194                 m_dirsToVisit.push_front(dir2);
     209                root.m_dirsToVisit.push_front(dir2);
    195210        }
    196211
     
    201216
    202217        // Check if we have already visited the directory
    203         if (!m_visitedDirs.insert(pDirectoryListing->path).second) {
     218        if (!root.m_visitedDirs.insert(pDirectoryListing->path).second) {
    204219                NextOperation();
    205220                return;
     
    225240
    226241        // Is operation restricted to a single child?
    227         bool restrict = !dir.restrict.empty();
     242        bool const restrict = static_cast<bool>(dir.restrict);
    228243
    229244        std::deque<wxString> filesToDelete;
     
    237252
    238253                if (restrict) {
    239                         if (entry.name != dir.restrict)
     254                        if (entry.name != *dir.restrict)
    240255                                continue;
    241256                }
    242                 else if (filter.FilenameFiltered(m_filters, entry.name, path, entry.is_dir(), entry.size, false, 0, entry.time))
     257                else if (filter.FilenameFiltered(m_filters, entry.name, path, entry.is_dir(), entry.size, 0, entry.time))
    243258                        continue;
    244259
     
    249264                if (entry.is_dir() && (!entry.is_link() || m_operationMode != recursive_delete)) {
    250265                        if (dir.recurse) {
    251                                 CNewDir dirToVisit;
     266                                recursion_root::new_dir dirToVisit;
    252267                                dirToVisit.parent = pDirectoryListing->path;
    253268                                dirToVisit.subdir = entry.name;
     
    261276                                        dirToVisit.recurse = false;
    262277                                }
    263                                 m_dirsToVisit.push_front(dirToVisit);
     278                                root.m_dirsToVisit.push_front(dirToVisit);
    264279                        }
    265280                }
     
    340355                m_pState->NotifyHandlers(STATECHANGE_RECURSION_STATUS);
    341356        }
    342         m_dirsToVisit.clear();
    343         m_visitedDirs.clear();
     357        recursion_roots_.clear();
    344358
    345359        if (m_pChmodDlg) {
     
    351365void CRecursiveOperation::ListingFailed(int error)
    352366{
    353         if (m_operationMode == recursive_none)
     367        if (m_operationMode == recursive_none || recursion_roots_.empty())
    354368                return;
    355369
     
    360374        }
    361375
    362         wxASSERT(!m_dirsToVisit.empty());
    363         if (m_dirsToVisit.empty())
    364                 return;
    365 
    366         CNewDir dir = m_dirsToVisit.front();
    367         m_dirsToVisit.pop_front();
    368         if ((error & FZ_REPLY_CRITICALERROR) != FZ_REPLY_CRITICALERROR && !dir.second_try)
    369         {
     376        auto & root = recursion_roots_.front();
     377        wxCHECK_RET(!root.m_dirsToVisit.empty(), _T("Empty dirs to visit"));
     378
     379        recursion_root::new_dir dir = root.m_dirsToVisit.front();
     380        root.m_dirsToVisit.pop_front();
     381        if ((error & FZ_REPLY_CRITICALERROR) != FZ_REPLY_CRITICALERROR && !dir.second_try) {
    370382                // Retry, could have been a temporary socket creating failure
    371383                // (e.g. hitting a blocked port) or a disconnect (e.g. no-filetransfer-timeout)
    372384                dir.second_try = true;
    373                 m_dirsToVisit.push_front(dir);
     385                root.m_dirsToVisit.push_front(dir);
    374386        }
    375387
     
    394406void CRecursiveOperation::LinkIsNotDir()
    395407{
    396         if (m_operationMode == recursive_none)
    397                 return;
    398 
    399         wxASSERT(!m_dirsToVisit.empty());
    400         if (m_dirsToVisit.empty())
    401                 return;
    402 
    403         CNewDir dir = m_dirsToVisit.front();
    404         m_dirsToVisit.pop_front();
     408        if (m_operationMode == recursive_none || recursion_roots_.empty())
     409                return;
     410
     411        auto & root = recursion_roots_.front();
     412        wxCHECK_RET(!root.m_dirsToVisit.empty(), _T("Empty dirs to visit"));
     413
     414        recursion_root::new_dir dir = root.m_dirsToVisit.front();
     415        root.m_dirsToVisit.pop_front();
    405416
    406417        const CServer* pServer = m_pState->GetServer();
Note: See TracChangeset for help on using the changeset viewer.