//--------------------------------------------------------------------------
/// Returns the values of editable commands
/// \return XML containing the values of editable commands
//--------------------------------------------------------------------------
string CommandProcessor::GetEditableCommandValues()
{
    stringstream strOut;

    // give derived classes a chance to update / add settings.
    strOut << GetDerivedSettings();

    // now add this processors editable commands (Settings).
    CommandList::const_iterator objIter;

    for (objIter = m_Commands.begin(); objIter < m_Commands.end(); ++objIter)
    {
        CommandResponse* pObj = *objIter;
        PsAssert(pObj != NULL);

        if (pObj->GetEditableContent() != NOT_EDITABLE)
        {
            strOut << "<";
            strOut << pObj->GetTagName();
            strOut << " name='";
            strOut << pObj->GetDisplayName();
            strOut << "' url='";
            strOut << GetFullPathString().asCharArray();
            strOut << "'>";
            strOut << pObj->GetEditableContentValue();
            strOut << "</";
            strOut << pObj->GetTagName();
            strOut << ">";
        }
    }

    return strOut.str();
}
//--------------------------------------------------------------------------
/// Returns the CommandTree as XML based on the contents of this Processor
/// \return XML describing the added commands and Processors
//--------------------------------------------------------------------------
string CommandProcessor::GetCommandTree()
{
    stringstream strOut;

    // Add the link to the settings. Only add this link if there are editable items.
    if (GetEditableCount() > 0)
    {
        strOut << "<" << GetTagName() << "Settings name='Settings' url='" << GetFullPathString().asCharArray() << "/settings.xml' display='true'>";
        strOut << "</" << GetTagName() << "Settings>";
    }

    // Add the child nodes
    CommandList::const_iterator objIter;

    for (objIter = m_Commands.begin(); objIter < m_Commands.end(); ++objIter)
    {
        CommandResponse* pObj = *objIter;
        PsAssert(pObj != NULL);

        if (pObj->GetTreeInclude())
        {
            strOut << "<" << pObj->GetTagName() << " name='" << pObj->GetDisplayName() << "' url='";

            if (pObj->GetURL() != NULL)
            {
                strOut << GetFullPathString().asCharArray() << "/" << pObj->GetURL();
            }

            strOut << "' ";

            if (pObj->GetEditableContent() != NOT_EDITABLE)
            {
                strOut << "editable='TRUE' ";
            }

            strOut << "display='" << GetUIDisplayModeString(pObj->GetUIDisplayMode()) << "' prefix='";
            strOut << GetTitlePrefix() << "' ></" << pObj->GetTagName() << ">";
        }
    }

    // Add the sub-tree
    vector<CommandProcessor*>::const_iterator it;

    for (it = m_Processors.begin() ; it < m_Processors.end(); ++it)
    {
        CommandProcessor* pProc = *it;
        PsAssert(pProc != NULL);

        strOut << "<" << pProc->GetTagName() << " name='" << pProc->GetDisplayName() << "' id='";
        strOut << pProc->GetID() << "' display='" << GetUIDisplayModeString(pProc->GetUIDisplayMode());
        strOut << "' url='" << pProc->GetFullPathString().asCharArray() << "' prefix='" << GetTitlePrefix() << "'";

        string derivedAttrs = pProc->GetDerivedAttributes();

        if (!derivedAttrs.empty())
        {
            strOut << " " << derivedAttrs;
        }

        strOut << ">";

        strOut << pProc->GetCommandTree();

        strOut << "</" << pProc->GetTagName() << ">";
    }

    return strOut.str();
}
Exemple #3
0
void CCachedDirectory::RefreshStatus(bool bRecursive)
{
    // Make sure that our own status is up-to-date
    GetStatusForMember(m_directoryPath,bRecursive);

    CTSVNPathList updatePathList;
    CTSVNPathList crawlPathList;
    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": RefreshStatus for %s\n"), m_directoryPath.GetWinPath());

    DWORD now = GetTickCount();
    {
        // get the file write times with FindFirstFile/FindNextFile since those
        // APIs only access the folder, not each file individually.
        // This reduces the disk access a *lot*.
        std::map<CStringA, ULONGLONG> filetimes;
        WIN32_FIND_DATA FindFileData;
        CAutoFindFile hFind = FindFirstFile(m_directoryPath.GetWinPathString() + L"\\*.*", &FindFileData);
        if (hFind)
        {
            while (FindNextFile(hFind, &FindFileData))
            {
                if ( (wcscmp(FindFileData.cFileName, L"..")==0) ||
                     (wcscmp(FindFileData.cFileName, L".")==0) )
                     continue;
                ULARGE_INTEGER ft;
                ft.LowPart = FindFileData.ftLastWriteTime.dwLowDateTime;
                ft.HighPart = FindFileData.ftLastWriteTime.dwHighDateTime;

                CStringA nameUTF8 = CUnicodeUtils::GetUTF8(FindFileData.cFileName);
                filetimes[nameUTF8] = ft.QuadPart;
            }
            hFind.CloseHandle(); // explicit close handle to shorten its life time
        }

        AutoLocker lock(m_critSec);
        // We also need to check if all our file members have the right date on them
        for (CacheEntryMap::iterator itMembers = m_entryCache.begin(); itMembers != m_entryCache.end(); ++itMembers)
        {
            if ((itMembers->first)&&(!itMembers->first.IsEmpty()))
            {
                CTSVNPath filePath (GetFullPathString (itMembers->first));
                if (!filePath.IsEquivalentToWithoutCase(m_directoryPath))
                {
                    // we only have file members in our entry cache
                    ATLASSERT(!itMembers->second.IsDirectory());

                    auto ftIt = filetimes.find(itMembers->first.Mid(1));
                    if (ftIt != filetimes.end())
                    {
                        ULONGLONG ft = ftIt->second;
                        if ((itMembers->second.HasExpired(now))||(!itMembers->second.DoesFileTimeMatch(ft)))
                        {
                            // We need to request this item as well
                            updatePathList.AddPath(filePath);
                        }
                    }
                }
            }
        }

        if (bRecursive)
        {
            // crawl all sub folders too! Otherwise a change deep inside the
            // tree which has changed won't get propagated up the tree.
            for(ChildDirStatus::const_iterator it = m_childDirectories.begin(); it != m_childDirectories.end(); ++it)
            {
                CTSVNPath path;
                CString winPath = CUnicodeUtils::GetUnicode (it->first);
                path.SetFromWin (winPath, true);

                crawlPathList.AddPath(path);
            }
        }
    }

    for (int i = 0; i < updatePathList.GetCount(); ++i)
        GetStatusForMember(updatePathList[i], bRecursive);

    for (int i = 0; i < crawlPathList.GetCount(); ++i)
        CSVNStatusCache::Instance().AddFolderForCrawling(crawlPathList[i]);
}