//-------------------------------------------------------------------------- /// 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(); }
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]); }