/usr/lib/python2.7/dist-packages/cvs2svn_lib/svn_revision_range.py is in cvs2svn 2.4.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | # (Be in -*- python -*- mode.)
#
# ====================================================================
# Copyright (c) 2000-2008 CollabNet. All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://subversion.tigris.org/license-1.html.
# If newer versions of this license are posted there, you may use a
# newer version instead, at your option.
#
# This software consists of voluntary contributions made by many
# individuals. For exact contribution history, see the revision
# history and logs, available at http://cvs2svn.tigris.org/.
# ====================================================================
"""This module contains the SVNRevisionRange class."""
import bisect
from cvs2svn_lib.common import SVN_INVALID_REVNUM
class SVNRevisionRange:
"""The range of subversion revision numbers from which a path can be
copied. self.opening_revnum is the number of the earliest such
revision, and self.closing_revnum is one higher than the number of
the last such revision. If self.closing_revnum is None, then no
closings were registered."""
def __init__(self, source_lod, opening_revnum):
self.source_lod = source_lod
self.opening_revnum = opening_revnum
self.closing_revnum = None
def add_closing(self, closing_revnum):
# When we have a non-trunk default branch, we may have multiple
# closings--only register the first closing we encounter.
if self.closing_revnum is None:
self.closing_revnum = closing_revnum
def __contains__(self, revnum):
"""Return True iff REVNUM is contained in the range."""
return (
self.opening_revnum <= revnum \
and (self.closing_revnum is None or revnum < self.closing_revnum)
)
def __str__(self):
if self.closing_revnum is None:
return '[%d:]' % (self.opening_revnum,)
else:
return '[%d:%d]' % (self.opening_revnum, self.closing_revnum,)
def __repr__(self):
return str(self)
class RevisionScores:
"""Represent the scores for a range of revisions."""
def __init__(self, svn_revision_ranges):
"""Initialize based on SVN_REVISION_RANGES.
SVN_REVISION_RANGES is a list of SVNRevisionRange objects.
The score of an svn source is defined to be the number of
SVNRevisionRanges on that LOD that include the revision. A score
thus indicates that copying the corresponding revision (or any
following revision up to the next revision in the list) of the
object in question would yield that many correct paths at or
underneath the object. There may be other paths underneath it
that are not correct and would need to be deleted or recopied;
those can only be detected by descending and examining their
scores.
If SVN_REVISION_RANGES is empty, then all scores are undefined."""
deltas_map = {}
for range in svn_revision_ranges:
source_lod = range.source_lod
try:
deltas = deltas_map[source_lod]
except:
deltas = []
deltas_map[source_lod] = deltas
deltas.append((range.opening_revnum, +1))
if range.closing_revnum is not None:
deltas.append((range.closing_revnum, -1))
# A map:
#
# {SOURCE_LOD : [(REV1 SCORE1), (REV2 SCORE2), (REV3 SCORE3), ...]}
#
# where the tuples are sorted by revision number and the revision
# numbers are distinct. Score is the number of correct paths that
# would result from using the specified SOURCE_LOD and revision
# number (or any other revision preceding the next revision
# listed) as a source. For example, the score of any revision REV
# in the range REV2 <= REV < REV3 is equal to SCORE2.
self._scores_map = {}
for (source_lod,deltas) in deltas_map.items():
# Sort by revision number:
deltas.sort()
# Initialize output list with zeroth element of deltas. This
# element must exist, because it was verified that
# svn_revision_ranges (and therefore openings) is not empty.
scores = [ deltas[0] ]
total = deltas[0][1]
for (rev, change) in deltas[1:]:
total += change
if rev == scores[-1][0]:
# Same revision as last entry; modify last entry:
scores[-1] = (rev, total)
else:
# Previously-unseen revision; create new entry:
scores.append((rev, total))
self._scores_map[source_lod] = scores
def get_score(self, range):
"""Return the score for RANGE's opening revision.
If RANGE doesn't appear explicitly in self.scores, use the score
of the higest revision preceding RANGE. If there are no preceding
revisions, then the score for RANGE is unknown; in this case,
return -1."""
try:
scores = self._scores_map[range.source_lod]
except KeyError:
return -1
# Remember, according to the tuple sorting rules,
#
# (revnum, anything,) < (revnum+1,) < (revnum+1, anything,)
predecessor_index = bisect.bisect_right(
scores, (range.opening_revnum + 1,)
) - 1
if predecessor_index < 0:
return -1
return scores[predecessor_index][1]
def get_best_revnum(self):
"""Find the revnum with the highest score.
Return (revnum, score) for the revnum with the highest score. If
the highest score is shared by multiple revisions, select the
oldest revision."""
best_source_lod = None
best_revnum = SVN_INVALID_REVNUM
best_score = 0
source_lods = self._scores_map.keys()
source_lods.sort()
for source_lod in source_lods:
for revnum, score in self._scores_map[source_lod]:
if score > best_score:
best_source_lod = source_lod
best_score = score
best_revnum = revnum
return best_source_lod, best_revnum, best_score
|