CLogChangedPath::CLogChangedPath ( const CRevisionInfoContainer::CChangesIterator& iter , const CDictionaryBasedTempPath& logPath) : path (iter.GetPath()) , copyFromPath (NULL, (index_t)NO_INDEX) , copyFromRev (0) { flags.nodeKind = static_cast<svn_node_kind_t>(iter->GetPathType()); flags.action = (DWORD)iter.GetAction() / 4; flags.textModifies = static_cast<svn_tristate_t>(iter->GetTextModifies()); flags.propsModifies = static_cast<svn_tristate_t>(iter->GetPropsModifies()); // check relevance for log path flags.relevantForStartPath = logPath.IsSameOrParentOf (path) || logPath.IsSameOrChildOf (path); // set copy-from info, if available if (iter.HasFromPath() && (iter.GetFromRevision() != NO_REVISION)) { copyFromPath = iter.GetFromPath(); copyFromRev = iter.GetFromRevision(); } }
bool CLogIteratorBase::InternalHandleCopyAndDelete ( const CRevisionInfoContainer::CChangesIterator& first , const CRevisionInfoContainer::CChangesIterator& last , const CDictionaryBasedPath& revisionRootPath) { // any chance that this revision affects our search path? if (!revisionRootPath.IsValid()) return false; if (!revisionRootPath.IsSameOrParentOf (path.GetBasePath())) return false; // close examination of all changes CRevisionInfoContainer::CChangesIterator bestRename = last; for ( CRevisionInfoContainer::CChangesIterator iter = first ; iter != last ; ++iter) { // most entries will just be file content changes // -> skip them efficiently CRevisionInfoContainer::TChangeAction action = iter.GetAction(); if (action == CRevisionInfoContainer::ACTION_CHANGED) continue; // deletion / copy / rename / replacement // -> skip, if our search path is not affected (only some sub-path) CDictionaryBasedPath changedPath = iter->GetPath(); if (!changedPath.IsSameOrParentOf (path.GetBasePath())) continue; // now, this is serious switch (action) { // rename? case CRevisionInfoContainer::ACTION_ADDED: case CRevisionInfoContainer::ACTION_REPLACED: case CRevisionInfoContainer::ACTION_MOVED: case CRevisionInfoContainer::ACTION_MOVEREPLACED: { if (iter.HasFromPath()) { // continue search on copy source path // The last copy found will also be the one closed // to our searchPath (there may be multiple renames, // if the base path got renamed). assert ( ((bestRename == last) || (bestRename.GetPathID() < iter.GetPathID())) && "parent ADDs are not in strict order"); bestRename = iter; } else { // as part of a copy / rename, the parent path // may have been added in just the same revision. // // example: // // our path: /trunk/file // renamed to // /trunk/project/file // // this can only happen if // /trunk/project // is added first (usually without a copy from path) // // Stop iteration only if we found an ADD of // the exact search path. if (path == changedPath) { // the path we are following actually started here. addRevision = revision; addPath = path; revision = (revision_t)NO_REVISION; path.Invalidate(); return true; } } } break; case CRevisionInfoContainer::ACTION_DELETED: { // deletions are possible! // but we don't need to do anything with them. } break; // there should be no other default: { assert (0); } } } // there was a rename / copy from some older path,rev if (bestRename != last) { addRevision = revision; addPath = path; path = path.ReplaceParent ( bestRename.GetPath() , bestRename.GetFromPath()); revision = bestRename.GetFromRevision(); return true; } // all fine, no special action required return false; }