Document changes made since last edit of CHANGES.
[cvs2svn.git] / cvs2svn_lib / changeset.py
blob1022e0a977c2ea27d11da4a713acc22efee73a9f
1 # (Be in -*- python -*- mode.)
3 # ====================================================================
4 # Copyright (c) 2006-2008 CollabNet. All rights reserved.
6 # This software is licensed as described in the file COPYING, which
7 # you should have received as part of this distribution. The terms
8 # are also available at http://subversion.tigris.org/license-1.html.
9 # If newer versions of this license are posted there, you may use a
10 # newer version instead, at your option.
12 # This software consists of voluntary contributions made by many
13 # individuals. For exact contribution history, see the revision
14 # history and logs, available at http://cvs2svn.tigris.org/.
15 # ====================================================================
17 """Manage change sets."""
20 from cvs2svn_lib.common import InternalError
21 from cvs2svn_lib.context import Ctx
22 from cvs2svn_lib.symbol import Branch
23 from cvs2svn_lib.symbol import Tag
24 from cvs2svn_lib.time_range import TimeRange
25 from cvs2svn_lib.changeset_graph_node import ChangesetGraphNode
28 class Changeset(object):
29 """A set of cvs_items that might potentially form a single change set."""
31 def __init__(self, id, cvs_item_ids):
32 self.id = id
33 self.cvs_item_ids = list(cvs_item_ids)
35 def iter_cvs_items(self):
36 """Yield the CVSItems within this Changeset."""
38 for (id, cvs_item) in Ctx()._cvs_items_db.get_many(self.cvs_item_ids):
39 assert cvs_item is not None
40 yield cvs_item
42 def get_projects_opened(self):
43 """Return the set of projects that might be opened by this changeset."""
45 raise NotImplementedError()
47 def create_graph_node(self, cvs_item_to_changeset_id):
48 """Return a ChangesetGraphNode for this Changeset."""
50 raise NotImplementedError()
52 def create_split_changeset(self, id, cvs_item_ids):
53 """Return a Changeset with the specified contents.
55 This method is only implemented for changesets that can be split.
56 The type of the new changeset should be the same as that of SELF,
57 and any other information from SELF should also be copied to the
58 new changeset."""
60 raise NotImplementedError()
62 def __getstate__(self):
63 return (self.id, self.cvs_item_ids,)
65 def __setstate__(self, state):
66 (self.id, self.cvs_item_ids,) = state
68 def __cmp__(self, other):
69 raise NotImplementedError()
71 def __str__(self):
72 raise NotImplementedError()
74 def __repr__(self):
75 return '%s [%s]' % (
76 self, ', '.join(['%x' % id for id in self.cvs_item_ids]),)
79 class RevisionChangeset(Changeset):
80 """A Changeset consisting of CVSRevisions."""
82 _sort_order = 3
84 def create_graph_node(self, cvs_item_to_changeset_id):
85 time_range = TimeRange()
86 pred_ids = set()
87 succ_ids = set()
89 for cvs_item in self.iter_cvs_items():
90 time_range.add(cvs_item.timestamp)
92 for pred_id in cvs_item.get_pred_ids():
93 changeset_id = cvs_item_to_changeset_id.get(pred_id)
94 if changeset_id is not None:
95 pred_ids.add(changeset_id)
97 for succ_id in cvs_item.get_succ_ids():
98 changeset_id = cvs_item_to_changeset_id.get(succ_id)
99 if changeset_id is not None:
100 succ_ids.add(changeset_id)
102 return ChangesetGraphNode(self, time_range, pred_ids, succ_ids)
104 def create_split_changeset(self, id, cvs_item_ids):
105 return RevisionChangeset(id, cvs_item_ids)
107 def __cmp__(self, other):
108 return cmp(self._sort_order, other._sort_order) \
109 or cmp(self.id, other.id)
111 def __str__(self):
112 return 'RevisionChangeset<%x>' % (self.id,)
115 class OrderedChangeset(Changeset):
116 """A Changeset of CVSRevisions whose preliminary order is known.
118 The first changeset ordering involves only RevisionChangesets, and
119 results in a full ordering of RevisionChangesets (i.e., a linear
120 chain of dependencies with the order consistent with the
121 dependencies). These OrderedChangesets form the skeleton for the
122 full topological sort that includes SymbolChangesets as well."""
124 _sort_order = 2
126 def __init__(self, id, cvs_item_ids, ordinal, prev_id, next_id):
127 Changeset.__init__(self, id, cvs_item_ids)
129 # The order of this changeset among all OrderedChangesets:
130 self.ordinal = ordinal
132 # The changeset id of the previous OrderedChangeset, or None if
133 # this is the first OrderedChangeset:
134 self.prev_id = prev_id
136 # The changeset id of the next OrderedChangeset, or None if this
137 # is the last OrderedChangeset:
138 self.next_id = next_id
140 def get_projects_opened(self):
141 retval = set()
142 for cvs_item in self.iter_cvs_items():
143 retval.add(cvs_item.cvs_file.project)
144 return retval
146 def create_graph_node(self, cvs_item_to_changeset_id):
147 time_range = TimeRange()
149 pred_ids = set()
150 succ_ids = set()
152 if self.prev_id is not None:
153 pred_ids.add(self.prev_id)
155 if self.next_id is not None:
156 succ_ids.add(self.next_id)
158 for cvs_item in self.iter_cvs_items():
159 time_range.add(cvs_item.timestamp)
161 for pred_id in cvs_item.get_symbol_pred_ids():
162 changeset_id = cvs_item_to_changeset_id.get(pred_id)
163 if changeset_id is not None:
164 pred_ids.add(changeset_id)
166 for succ_id in cvs_item.get_symbol_succ_ids():
167 changeset_id = cvs_item_to_changeset_id.get(succ_id)
168 if changeset_id is not None:
169 succ_ids.add(changeset_id)
171 return ChangesetGraphNode(self, time_range, pred_ids, succ_ids)
173 def __getstate__(self):
174 return (
175 Changeset.__getstate__(self),
176 self.ordinal, self.prev_id, self.next_id,)
178 def __setstate__(self, state):
179 (changeset_state, self.ordinal, self.prev_id, self.next_id,) = state
180 Changeset.__setstate__(self, changeset_state)
182 def __cmp__(self, other):
183 return cmp(self._sort_order, other._sort_order) \
184 or cmp(self.id, other.id)
186 def __str__(self):
187 return 'OrderedChangeset<%x(%d)>' % (self.id, self.ordinal,)
190 class SymbolChangeset(Changeset):
191 """A Changeset consisting of CVSSymbols."""
193 def __init__(self, id, symbol, cvs_item_ids):
194 Changeset.__init__(self, id, cvs_item_ids)
195 self.symbol = symbol
197 def get_projects_opened(self):
198 # A SymbolChangeset can never open a project.
199 return set()
201 def create_graph_node(self, cvs_item_to_changeset_id):
202 pred_ids = set()
203 succ_ids = set()
205 for cvs_item in self.iter_cvs_items():
206 for pred_id in cvs_item.get_pred_ids():
207 changeset_id = cvs_item_to_changeset_id.get(pred_id)
208 if changeset_id is not None:
209 pred_ids.add(changeset_id)
211 for succ_id in cvs_item.get_succ_ids():
212 changeset_id = cvs_item_to_changeset_id.get(succ_id)
213 if changeset_id is not None:
214 succ_ids.add(changeset_id)
216 return ChangesetGraphNode(self, TimeRange(), pred_ids, succ_ids)
218 def __cmp__(self, other):
219 return cmp(self._sort_order, other._sort_order) \
220 or cmp(self.symbol, other.symbol) \
221 or cmp(self.id, other.id)
223 def __getstate__(self):
224 return (Changeset.__getstate__(self), self.symbol.id,)
226 def __setstate__(self, state):
227 (changeset_state, symbol_id) = state
228 Changeset.__setstate__(self, changeset_state)
229 self.symbol = Ctx()._symbol_db.get_symbol(symbol_id)
232 class BranchChangeset(SymbolChangeset):
233 """A Changeset consisting of CVSBranches."""
235 _sort_order = 1
237 def create_split_changeset(self, id, cvs_item_ids):
238 return BranchChangeset(id, self.symbol, cvs_item_ids)
240 def __str__(self):
241 return 'BranchChangeset<%x>("%s")' % (self.id, self.symbol,)
244 class TagChangeset(SymbolChangeset):
245 """A Changeset consisting of CVSTags."""
247 _sort_order = 0
249 def create_split_changeset(self, id, cvs_item_ids):
250 return TagChangeset(id, self.symbol, cvs_item_ids)
252 def __str__(self):
253 return 'TagChangeset<%x>("%s")' % (self.id, self.symbol,)
256 def create_symbol_changeset(id, symbol, cvs_item_ids):
257 """Factory function for SymbolChangesets.
259 Return a BranchChangeset or TagChangeset, depending on the type of
260 SYMBOL. SYMBOL must be a Branch or Tag."""
262 if isinstance(symbol, Branch):
263 return BranchChangeset(id, symbol, cvs_item_ids)
264 if isinstance(symbol, Tag):
265 return TagChangeset(id, symbol, cvs_item_ids)
266 else:
267 raise InternalError('Unknown symbol type %s' % (symbol,))