CDictionaryBasedTempPath CDictionaryBasedTempPath::ReplaceParent ( const CDictionaryBasedPath& oldParent , const CDictionaryBasedPath& newParent) const { assert (oldParent.IsSameOrParentOf (*this)); // I admit, this is the most stupid implementation possible ;) std::string newPath = newParent.GetPath() + GetPath().substr (oldParent.GetPath().length()); return CDictionaryBasedTempPath (GetDictionary(), newPath); }
bool CLogIteratorBase::PathInRevision ( const CRevisionInfoContainer::CChangesIterator& first , const CRevisionInfoContainer::CChangesIterator& last , const CDictionaryBasedTempPath& path) { // close examination of all changes for ( CRevisionInfoContainer::CChangesIterator iter = first ; iter != last ; ++iter) { // if (and only if) path is a cached path, // it may be a parent of the changedPath // (i.e. report a change of this or some sub-path) CDictionaryBasedPath changedPath = iter->GetPath(); if ( path.IsFullyCachedPath() && path.GetBasePath().IsSameOrParentOf (changedPath)) return true; // this change affects a true parent path or completely unrelated path // -> ignore mere modifications (e.g. properties on a folder) if (iter->GetAction() == CRevisionInfoContainer::ACTION_CHANGED) continue; // this is an add / delete / replace. // does it affect our path? if (changedPath.IsSameOrParentOf (path.GetBasePath())) return true; } // no paths that we were looking for return false; }
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; }