bool CLogIteratorBase::PathInRevision() const { assert (!InternalDataIsMissing()); // special case: repository root // (report all revisions including empty ones) if (path.IsRoot()) return true; // if we don't have a path, we won't find any changes if (!path.IsValid()) return false; // revision data lookup revision_t index = revisionIndices[revision]; // any chance that this revision affects our path? CDictionaryBasedPath revisionRootPath = revisionInfo.GetRootPath (index); if (!revisionRootPath.IsValid()) return false; if (!path.GetBasePath().Intersects (revisionRootPath)) return false; // close examination of all changes return PathInRevision ( revisionInfo.GetChangesBegin(index) , revisionInfo.GetChangesEnd(index) , path); }
revision_t CSkipRevisionInfo::GetPreviousRevision ( const CDictionaryBasedPath& path , revision_t revision) const { // above the root or invalid parameter ? if (!path.IsValid() || (revision == NO_REVISION)) return (revision_t)NO_REVISION; // lookup the entry for this path index_t dataIndex = index.find (path.GetIndex()); SPerPathRanges* ranges = dataIndex == NO_INDEX ? NULL : data[dataIndex]; // crawl this and the parent path data // until we found a gap (i.e. could not improve further) revision_t startRevision = revision; revision_t result = revision; do { result = revision; revision_t parentNext = GetPreviousRevision (path.GetParent(), revision); if (parentNext != NO_REVISION) revision = parentNext; if (ranges != NULL) { revision_t next = ranges->FindPrevious (revision); if (next != NO_REVISION) revision = next; } } while (revision < result); // ready return revision == startRevision ? NO_REVISION : result; }
void CSkipRevisionInfo::Add ( const CDictionaryBasedPath& path , revision_t revision , revision_t size) { // violating these assertions will break our lookup algorithms assert (path.IsValid()); assert (revision != NO_REVISION); assert (size != NO_REVISION); assert (2*size > size); // reduce the range, if we have revision info at the boundaries TryReduceRange (revision, size); if (size == 0) return; // lookup / auto-insert entry for path SPerPathRanges* ranges = NULL; index_t dataIndex = index.find (path.GetIndex()); if (dataIndex == NO_INDEX) { ranges = new SPerPathRanges; ranges->pathID = path.GetIndex(); data.push_back (ranges); index.insert (path.GetIndex(), (index_t)data.size()-1); } else { ranges = data[dataIndex]; } // add range ranges->Add (revision, size); }
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; }