Changeset 614 in tailor
- Timestamp:
- 08/17/05 19:49:32 (8 years ago)
- Hash name:
- 20050817174932-97f81-ed13a41218cda9683aafa49551b6432786b3e1a1
- Location:
- vcpx
- Files:
-
- 1 added
- 5 edited
-
changes.py (modified) (1 diff)
-
cvsps.py (modified) (3 diffs)
-
source.py (modified) (5 diffs)
-
tests/__init__.py (modified) (1 diff)
-
project.py (modified) (2 diffs)
-
tests/statefile.py (added)
Legend:
- Unmodified
- Added
- Removed
-
vcpx/changes.py
r520 r614 117 117 self.entries = entries or [] 118 118 self.unidiff = None # This is the unidiff of the whole changeset 119 120 def __eq__(self, other): 121 return (self.revision == other.revision and 122 self.date == other.date and 123 self.author == other.author) 124 125 def __ne__(self, other): 126 return (self.revision <> other.revision or 127 self.date <> other.date or 128 self.author <> other.author) 119 129 120 130 def addEntry(self, entry, revision): -
vcpx/cvsps.py
r594 r614 285 285 286 286 if timestamp == 'INITIAL': 287 timestamp = csets[0].date.isoformat(sep=' ') 287 cset = csets.next() 288 timestamp = cset.date.isoformat(sep=' ') 289 else: 290 cset = None 288 291 289 292 if not exists(join(self.basedir, 'CVS')): … … 320 323 321 324 found = False 322 while csets: 323 cset = csets.pop(0) 325 if cset is None: 326 try: 327 cset = csets.next() 328 except StopIteration: 329 cset = None 330 while cset is not None: 324 331 for m in cset.entries: 325 332 info = entries.getFileInfo(m.name) … … 333 340 last = cset 334 341 break 342 343 try: 344 cset = csets.next() 345 except StopIteration: 346 cset = None 335 347 336 348 if not found: -
vcpx/source.py
r579 r614 83 83 conflicts = [] 84 84 85 if not self.pending:86 return last, conflicts87 88 85 try: 89 while self.pending: 90 c = self.pending[0] 91 86 for c in self.state_file: 92 87 # Give the opportunity to subclasses to stop the application 93 88 # of the queue, before the application of the patch by the … … 123 118 replay(c) 124 119 125 # Remove it from the queue and remember it for the finally 126 # clause 127 last = self.pending.pop(0) 120 # Remember it for the finally clause and notify the state 121 # file so that it gets removed from the queue 122 last = c 123 self.state_file.applied() 128 124 129 125 # Another hook (last==c here) … … 132 128 finally: 133 129 # For whatever reason we exit the loop, save the last state 134 if last is not None: 135 self.state_file.write(last.revision, self.pending) 130 self.state_file.finalize() 136 131 137 132 return last, conflicts … … 181 176 """ 182 177 Load the pending changesets from the state file, or query the 183 upstream repository if there's none. 184 """ 185 186 revision, self.pending = self.state_file.load() 187 if not self.pending: 188 self.pending = self._getUpstreamChangesets(revision or sincerev) 189 return self.pending 178 upstream repository if there's none. Return an iterator over 179 pending changesets. 180 """ 181 182 pending = len(self.state_file) 183 if pending == 0: 184 last = self.state_file.lastAppliedChangeset() 185 if last: 186 revision = last.revision 187 else: 188 revision = sincerev 189 changesets = self._getUpstreamChangesets(revision) 190 self.state_file.setPendingChangesets(changesets) 191 return self.state_file 190 192 191 193 def _getUpstreamChangesets(self, sincerev): … … 219 221 220 222 last = self._checkoutUpstreamRevision(revision) 221 self.state_file.write(last.revision, getattr(self, 'pending', None)) 223 self.state_file.applied(last) 224 # Some backend may have already fetched the remaining history 225 pending = getattr(self, 'pending', None) 226 if pending: 227 self.state_file.setPendingChangesets(pending) 222 228 return last 223 229 -
vcpx/tests/__init__.py
r524 r614 12 12 from svn import * 13 13 from config import * 14 from statefile import * 14 15 from tailor import * 15 16 -
vcpx/project.py
r603 r614 14 14 __docformat__ = 'reStructuredText' 15 15 16 from cPickle import load, dump 17 16 18 class StateFile(object): 17 19 """ 18 20 State file that stores current revision and pending changesets. 21 22 It behaves as an iterator, and source backends loop over not yet 23 applied changesets, calling .applied() after each one: that writes 24 the applied changeset in a `journal` file, much more atomic than 25 rewriting the whole archive each time. 26 27 When the source backend finishes it's job, either because there 28 are no more pending changeset or stopped by an error, it calls 29 .finalize(), that in presence of a journal file adjust the 30 archive filtering out already applied changesets. 31 32 Should an hard error prevent .finalize() call, it will happen 33 automatically next time the state file is loaded. 19 34 """ 35 20 36 def __init__(self, fname, config): 21 37 self.filename = fname 38 self.archive = None 39 self.last_applied = None 40 self.current = None 41 self.queuelen = 0 42 43 def _load(self): 44 """ 45 Open the pickle file and load the first two items, respectively 46 the revision and the number of pending changesets. 47 """ 48 49 # Take care of the journal file, if present. 50 self.finalize() 51 52 self.current = None 53 try: 54 self.archive = open(self.filename) 55 self.last_applied = load(self.archive) 56 self.queuelen = load(self.archive) 57 except IOError: 58 self.archive = None 59 self.last_applied = None 60 self.queuelen = 0 61 62 def _write(self, changesets): 63 """ 64 Write the state file. 65 """ 66 67 sf = open(self.filename, 'w') 68 dump(self.last_applied, sf) 69 dump(len(changesets), sf) 70 for cs in changesets: 71 dump(cs, sf) 72 sf.close() 22 73 23 74 def __str__(self): 24 75 return self.filename 25 76 26 def load(self): 27 """ 28 Read the source revision and pending changesets from the state file. 29 """ 30 31 from cPickle import load 32 33 try: 34 sf = open(self.filename) 35 revision, changesets = load(sf) 77 def __iter__(self): 78 return self 79 80 def next(self): 81 if not self.archive: 82 raise StopIteration 83 try: 84 self.current = load(self.archive) 85 except EOFError: 86 self.archive.close() 87 self.archive = None 88 raise StopIteration 89 self.queuelen -= 1 90 return self.current 91 92 def __len__(self): 93 if self.archive is None: 94 self._load() 95 return self.queuelen 96 97 def applied(self, current=None): 98 """ 99 Write the applied changeset to the journal file. 100 """ 101 102 self.last_applied = current or self.current 103 journal = open(self.filename + '.journal', 'w') 104 dump(self.last_applied, journal) 105 journal.close() 106 107 def finalize(self): 108 """ 109 If there is a journal file, adjust the archive accordingly, 110 dropping already applied changesets. 111 """ 112 113 from os.path import exists 114 from os import unlink, rename 115 116 if self.archive is not None: 117 self.archive.close() 118 self.archive = None 119 120 if not exists(self.filename + '.journal'): 121 return 122 123 # Load last applied changeset from the journal 124 journal = open(self.filename + '.journal') 125 last_applied = load(journal) 126 journal.close() 127 128 # If there is an actual archive (ie, this is not bootstrap time) 129 # load the changesets from there, skipping the changesets until 130 # the last_applied one, then transfer the remaining to the new 131 # archive. 132 if exists(self.filename): 133 old = open(self.filename) 134 load(old) # last applied 135 queuelen = load(old) 136 cs = load(old) 137 138 # Skip already applied changesets 139 while cs <> last_applied: 140 queuelen -= 1 141 cs = load(old) 142 143 sf = open(self.filename + '.new', 'w') 144 dump(last_applied, sf) 145 dump(queuelen-1, sf) 146 147 while True: 148 try: 149 cs = load(old) 150 except EOFError: 151 break 152 dump(cs, sf) 36 153 sf.close() 37 except IOError: 38 revision = None 39 changesets = None 40 41 return revision, changesets 42 43 def write(self, revision, changesets): 44 """ 45 Write current source revision and pending changesets in the state file. 46 """ 47 48 from cPickle import dump 49 50 sf = open(self.filename, 'w') 51 dump((revision, changesets), sf) 52 sf.close() 154 old.close() 155 unlink(self.filename) 156 rename(sf.name, self.filename) 157 else: 158 sf = open(self.filename, 'w') 159 dump(last_applied, sf) 160 dump(0, sf) 161 sf.close() 162 163 unlink(journal.name) 164 165 def lastAppliedChangeset(self): 166 """ 167 Return the last applied changeset, if any, None otherwise. 168 """ 169 170 if self.archive is None: 171 self._load() 172 return self.last_applied 173 174 def setPendingChangesets(self, changesets): 175 """ 176 Write pending changesets to the state file. 177 """ 178 179 if self.archive is not None: 180 self.archive.close() 181 self.archive = None 182 183 self._write(changesets) 184 self._load() 53 185 54 186 … … 179 311 """ 180 312 Return True if the project exists, False otherwise. 181 182 Check for the existence of the state file to decide. 183 """ 184 185 from os.path import exists 186 187 return exists(self.state_file.filename) 313 """ 314 315 return self.state_file.lastAppliedChangeset() is not None 188 316 189 317 def workingDir(self):
Note: See TracChangeset
for help on using the changeset viewer.
