Beispiel #1
0
void CCSVWriter::WriteSkipRanges (std::ostream& os, const CCachedLogInfo& cache)
{
	// header

	os << "PathID,Path,StartRevision,Length\n";

	// content

    const CSkipRevisionInfo& info = cache.GetSkippedRevisions();

	// ids will be added on-the-fly

	for (size_t i = 0; i < info.GetPathCount(); ++i)
	{
        CDictionaryBasedPath path = info.GetPath(i);
        CSkipRevisionInfo::TRanges ranges = info.GetRanges(i);

        for (size_t k = 0, count = ranges.size(); k < count; ++k)
        {
            os << path.GetIndex() << ",\"" 
               << path.GetPath().c_str() << "\","
			   << ranges[k].first << ','
			   << ranges[k].second
			   << "\n";
		}
	}
}
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);
}
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);
}
CString CLogChangedPath::GetUIPath (const CDictionaryBasedPath& p) const
{
    std::string utf8Path = p.GetPath();

    // we don't need to adjust the path length as
    // the conversion will automatically stop at \0.

    return CUnicodeUtils::UTF8ToUTF16 (utf8Path);
}
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::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;
}
CRemovePathsBySubString::PathClassification
CRemovePathsBySubString::QuickClassification (const CDictionaryBasedPath& path) const
{
    // ensure the index is valid within classification cache

    if (pathClassification.size() <= path.GetIndex())
    {
        size_t newSize = max (8, pathClassification.size()) * 2;
        while (newSize <= path.GetIndex())
            newSize *= 2;

        pathClassification.resize (newSize, UNKNOWN);
    }

    // auto-calculate the entry

    PathClassification& classification = pathClassification[path.GetIndex()];
    if (classification == UNKNOWN)
        classification = Classify (path.GetPath());

    // done here

    return classification;
}
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;
}