/usr/lib/python2.7/dist-packages/cvs2svn_lib/changeset_graph_link.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 | # (Be in -*- python -*- mode.)
#
# ====================================================================
# Copyright (c) 2006-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/.
# ====================================================================
"""Keep track of counts of different types of changeset links."""
# A cvs_item doesn't depend on any cvs_items in either pred or succ:
LINK_NONE = 0
# A cvs_item depends on one or more cvs_items in pred but none in succ:
LINK_PRED = 1
# A cvs_item depends on one or more cvs_items in succ but none in pred:
LINK_SUCC = 2
# A cvs_item depends on one or more cvs_items in both pred and succ:
LINK_PASSTHRU = LINK_PRED | LINK_SUCC
class ChangesetGraphLink(object):
def __init__(self, pred, changeset, succ):
"""Represent a link in a loop in a changeset graph.
This is the link that goes from PRED -> CHANGESET -> SUCC.
We are mainly concerned with how many CVSItems have LINK_PRED,
LINK_SUCC, and LINK_PASSTHRU type links to the neighboring
commitsets. If necessary, this class can also break up CHANGESET
into multiple changesets."""
self.pred = pred
self.pred_ids = set(pred.cvs_item_ids)
self.changeset = changeset
self.succ_ids = set(succ.cvs_item_ids)
self.succ = succ
# A count of each type of link for cvs_items in changeset
# (indexed by LINK_* constants):
link_counts = [0] * 4
for cvs_item in list(changeset.iter_cvs_items()):
link_counts[self.get_link_type(cvs_item)] += 1
[self.pred_links, self.succ_links, self.passthru_links] = link_counts[1:]
def get_link_type(self, cvs_item):
"""Return the type of links from CVS_ITEM to self.PRED and self.SUCC.
The return value is one of LINK_NONE, LINK_PRED, LINK_SUCC, or
LINK_PASSTHRU."""
retval = LINK_NONE
if cvs_item.get_pred_ids() & self.pred_ids:
retval |= LINK_PRED
if cvs_item.get_succ_ids() & self.succ_ids:
retval |= LINK_SUCC
return retval
def get_links_to_move(self):
"""Return the number of items that would be moved to split changeset."""
return min(self.pred_links, self.succ_links) \
or max(self.pred_links, self.succ_links)
def is_breakable(self):
"""Return True iff breaking the changeset will do any good."""
return self.pred_links != 0 or self.succ_links != 0
def __cmp__(self, other):
"""Compare SELF with OTHER in terms of which would be better to break.
The one that is better to break is considered the lesser."""
return (
- cmp(int(self.is_breakable()), int(other.is_breakable()))
or cmp(self.passthru_links, other.passthru_links)
or cmp(self.get_links_to_move(), other.get_links_to_move())
)
def break_changeset(self, changeset_key_generator):
"""Break up self.changeset and return the fragments.
Break it up in such a way that the link is weakened as efficiently
as possible."""
if not self.is_breakable():
raise ValueError('Changeset is not breakable: %r' % self.changeset)
pred_items = []
succ_items = []
# For each link type, should such CVSItems be moved to the
# changeset containing the predecessor items or the one containing
# the successor items?
destination = {
LINK_PRED : pred_items,
LINK_SUCC : succ_items,
}
if self.pred_links == 0:
destination[LINK_NONE] = pred_items
destination[LINK_PASSTHRU] = pred_items
elif self.succ_links == 0:
destination[LINK_NONE] = succ_items
destination[LINK_PASSTHRU] = succ_items
elif self.pred_links < self.succ_links:
destination[LINK_NONE] = succ_items
destination[LINK_PASSTHRU] = succ_items
else:
destination[LINK_NONE] = pred_items
destination[LINK_PASSTHRU] = pred_items
for cvs_item in self.changeset.iter_cvs_items():
link_type = self.get_link_type(cvs_item)
destination[link_type].append(cvs_item.id)
# Create new changesets of the same type as the old one:
return [
self.changeset.create_split_changeset(
changeset_key_generator.gen_id(), pred_items),
self.changeset.create_split_changeset(
changeset_key_generator.gen_id(), succ_items),
]
def __str__(self):
return 'Link<%x>(%d, %d, %d)' % (
self.changeset.id,
self.pred_links, self.succ_links, self.passthru_links)
|