Mercurial > hgsubversion
comparison hg_delta_editor.py @ 304:ce676eff002b
First merge, totally untested.
author | Dan Villiom Podlaski Christiansen <danchr@gmail.com> |
---|---|
date | Fri, 01 May 2009 10:28:59 +0200 |
parents | 4aba7542f6a9 153266401676 |
children | e6853c7fa3af |
comparison
equal
deleted
inserted
replaced
303:f423a8780832 | 304:ce676eff002b |
---|---|
6 import traceback | 6 import traceback |
7 | 7 |
8 from mercurial import context | 8 from mercurial import context |
9 from mercurial import hg | 9 from mercurial import hg |
10 from mercurial import ui | 10 from mercurial import ui |
11 from mercurial import util | 11 from mercurial import util as hgutil |
12 from mercurial import revlog | 12 from mercurial import revlog |
13 from mercurial import node | 13 from mercurial import node |
14 from svn import delta | 14 from svn import delta |
15 from svn import core | 15 from svn import core |
16 | 16 |
17 import svnexternals | 17 import svnexternals |
18 import util as our_util | 18 import util |
19 | 19 |
20 def pickle_atomic(data, file_path, dir=None): | 20 def pickle_atomic(data, file_path, dir=None): |
21 """pickle some data to a path atomically. | 21 """pickle some data to a path atomically. |
22 | 22 |
23 This is present because I kept corrupting my revmap by managing to hit ^C | 23 This is present because I kept corrupting my revmap by managing to hit ^C |
29 pickle.dump(data, f) | 29 pickle.dump(data, f) |
30 f.close() | 30 f.close() |
31 except: #pragma: no cover | 31 except: #pragma: no cover |
32 raise | 32 raise |
33 else: | 33 else: |
34 util.rename(path, file_path) | 34 hgutil.rename(path, file_path) |
35 | 35 |
36 def stash_exception_on_self(fn): | 36 def stash_exception_on_self(fn): |
37 """Stash any exception raised in the method on self. | 37 """Stash any exception raised in the method on self. |
38 | 38 |
39 This is required because the SWIG bindings just mutate any exception into | 39 This is required because the SWIG bindings just mutate any exception into |
58 f.flush() | 58 f.flush() |
59 f.close() | 59 f.close() |
60 self.revmap[revnum, branch] = node_hash | 60 self.revmap[revnum, branch] = node_hash |
61 | 61 |
62 def last_known_revision(self): | 62 def last_known_revision(self): |
63 ''' Obtain the highest numbered -- i.e. latest -- revision known. | 63 """Obtain the highest numbered -- i.e. latest -- revision known. |
64 | 64 |
65 Currently, this function just iterates over the entire revision map | 65 Currently, this function just iterates over the entire revision map |
66 using the max() builtin. This may be slow for extremely large | 66 using the max() builtin. This may be slow for extremely large |
67 repositories, but for now, it's fast enough. | 67 repositories, but for now, it's fast enough. |
68 ''' | 68 """ |
69 try: | 69 try: |
70 return max(k[0] for k in self.revmap.iterkeys()) | 70 return max(k[0] for k in self.revmap.iterkeys()) |
71 except ValueError: | 71 except ValueError: |
72 return 0 | 72 return 0 |
73 | 73 |
79 """path is the path to the target hg repo. | 79 """path is the path to the target hg repo. |
80 | 80 |
81 subdir is the subdirectory of the edits *on the svn server*. | 81 subdir is the subdirectory of the edits *on the svn server*. |
82 It is needed for stripping paths off in certain cases. | 82 It is needed for stripping paths off in certain cases. |
83 """ | 83 """ |
84 if repo and repo.ui and not ui_: | |
85 ui_ = repo.ui | |
84 if not ui_: | 86 if not ui_: |
85 ui_ = ui.ui() | 87 ui_ = ui.ui() |
86 self.ui = ui_ | 88 self.ui = ui_ |
87 if repo: | 89 if repo: |
88 self.repo = repo | 90 self.repo = repo |
96 self.subdir = subdir | 98 self.subdir = subdir |
97 if self.subdir and self.subdir[0] == '/': | 99 if self.subdir and self.subdir[0] == '/': |
98 self.subdir = self.subdir[1:] | 100 self.subdir = self.subdir[1:] |
99 self.revmap = {} | 101 self.revmap = {} |
100 if os.path.exists(self.revmap_file): | 102 if os.path.exists(self.revmap_file): |
101 self.revmap = our_util.parse_revmap(self.revmap_file) | 103 self.revmap = util.parse_revmap(self.revmap_file) |
102 self.branches = {} | 104 self.branches = {} |
103 if os.path.exists(self.branch_info_file): | 105 if os.path.exists(self.branch_info_file): |
104 f = open(self.branch_info_file) | 106 f = open(self.branch_info_file) |
105 self.branches = pickle.load(f) | 107 self.branches = pickle.load(f) |
106 f.close() | 108 f.close() |
128 self.readauthors(self.authors_file) | 130 self.readauthors(self.authors_file) |
129 if authors and os.path.exists(authors): | 131 if authors and os.path.exists(authors): |
130 self.readauthors(authors) | 132 self.readauthors(authors) |
131 if self.authors: | 133 if self.authors: |
132 self.writeauthors() | 134 self.writeauthors() |
135 | |
136 self.lastdate = '1970-01-01 00:00:00 -0000' | |
133 self.includepaths = {} | 137 self.includepaths = {} |
134 self.excludepaths = {} | 138 self.excludepaths = {} |
135 if filemap and os.path.exists(filemap): | 139 if filemap and os.path.exists(filemap): |
136 self.readfilemap(filemap) | 140 self.readfilemap(filemap) |
141 | |
142 def fixdate(self, date): | |
143 if date is not None: | |
144 date = date.replace('T', ' ').replace('Z', '').split('.')[0] | |
145 date += ' -0000' | |
146 self.lastdate = date | |
147 else: | |
148 date = self.lastdate | |
149 return date | |
137 | 150 |
138 def __setup_repo(self, repo_path): | 151 def __setup_repo(self, repo_path): |
139 """Verify the repo is going to work out for us. | 152 """Verify the repo is going to work out for us. |
140 | 153 |
141 This method will fail an assertion if the repo exists but doesn't have | 154 This method will fail an assertion if the repo exists but doesn't have |
148 assert os.path.isfile(self.uuid_file) | 161 assert os.path.isfile(self.uuid_file) |
149 else: | 162 else: |
150 self.repo = hg.repository(self.ui, repo_path, create=True) | 163 self.repo = hg.repository(self.ui, repo_path, create=True) |
151 os.makedirs(os.path.dirname(self.uuid_file)) | 164 os.makedirs(os.path.dirname(self.uuid_file)) |
152 f = open(self.revmap_file, 'w') | 165 f = open(self.revmap_file, 'w') |
153 f.write('%s\n' % our_util.REVMAP_FILE_VERSION) | 166 f.write('%s\n' % util.REVMAP_FILE_VERSION) |
154 f.flush() | 167 f.flush() |
155 f.close() | 168 f.close() |
156 | 169 |
157 def clear_current_info(self): | 170 def clear_current_info(self): |
158 '''Clear the info relevant to a replayed revision so that the next | 171 '''Clear the info relevant to a replayed revision so that the next |
204 paths_need_discovery = [p[1] for p in paths_need_discovery] | 217 paths_need_discovery = [p[1] for p in paths_need_discovery] |
205 actually_files = [] | 218 actually_files = [] |
206 while paths_need_discovery: | 219 while paths_need_discovery: |
207 p = paths_need_discovery.pop(0) | 220 p = paths_need_discovery.pop(0) |
208 path_could_be_file = True | 221 path_could_be_file = True |
209 # TODO(augie) Figure out if you can use break here in a for loop, quick | |
210 # testing of that failed earlier. | |
211 ind = 0 | 222 ind = 0 |
212 while ind < len(paths_need_discovery) and not paths_need_discovery: | 223 while ind < len(paths_need_discovery) and not paths_need_discovery: |
213 if op.startswith(p): | 224 if op.startswith(p): |
214 path_could_be_file = False | 225 path_could_be_file = False |
215 ind += 1 | 226 ind += 1 |
231 while filepaths: | 242 while filepaths: |
232 path = filepaths.pop(0) | 243 path = filepaths.pop(0) |
233 parentdir = '/'.join(path[:-1]) | 244 parentdir = '/'.join(path[:-1]) |
234 filepaths = [p for p in filepaths if not '/'.join(p).startswith(parentdir)] | 245 filepaths = [p for p in filepaths if not '/'.join(p).startswith(parentdir)] |
235 branchpath = self._normalize_path(parentdir) | 246 branchpath = self._normalize_path(parentdir) |
247 if branchpath.startswith('tags/'): | |
248 continue | |
236 branchname = self._localname(branchpath) | 249 branchname = self._localname(branchpath) |
237 if branchpath.startswith('trunk/'): | 250 if branchpath.startswith('trunk/'): |
238 branches[self._localname('trunk')] = 'trunk' | 251 branches[self._localname('trunk')] = 'trunk' |
239 continue | 252 continue |
253 if branchname and branchname.startswith('../'): | |
254 continue | |
240 branches[branchname] = branchpath | 255 branches[branchname] = branchpath |
241 | 256 |
242 return branches | 257 return branches |
243 | 258 |
244 def _path_and_branch_for_path(self, path, existing=True): | 259 def _path_and_branch_for_path(self, path, existing=True): |
248 return self._path_and_branch_for_path(path, existing=existing)[1] | 263 return self._path_and_branch_for_path(path, existing=existing)[1] |
249 | 264 |
250 def _localname(self, path): | 265 def _localname(self, path): |
251 """Compute the local name for a branch located at path. | 266 """Compute the local name for a branch located at path. |
252 """ | 267 """ |
268 assert not path.startswith('tags/') | |
253 if path == 'trunk': | 269 if path == 'trunk': |
254 return None | 270 return None |
255 elif path.startswith('branches/'): | 271 elif path.startswith('branches/'): |
256 return path[len('branches/'):] | 272 return path[len('branches/'):] |
257 return '../%s' % path | 273 return '../%s' % path |
272 If existing=True, will return None, None, None if the file isn't on some known | 288 If existing=True, will return None, None, None if the file isn't on some known |
273 branch. If existing=False, then it will guess what the branch would be if it were | 289 branch. If existing=False, then it will guess what the branch would be if it were |
274 known. | 290 known. |
275 """ | 291 """ |
276 path = self._normalize_path(path) | 292 path = self._normalize_path(path) |
293 if path.startswith('tags/'): | |
294 return None, None, None | |
277 test = '' | 295 test = '' |
278 path_comps = path.split('/') | 296 path_comps = path.split('/') |
279 while self._localname(test) not in self.branches and len(path_comps): | 297 while self._localname(test) not in self.branches and len(path_comps): |
280 if not test: | 298 if not test: |
281 test = path_comps.pop(0) | 299 test = path_comps.pop(0) |
286 if existing: | 304 if existing: |
287 return None, None, None | 305 return None, None, None |
288 if path.startswith('trunk/'): | 306 if path.startswith('trunk/'): |
289 path = test.split('/')[1:] | 307 path = test.split('/')[1:] |
290 test = 'trunk' | 308 test = 'trunk' |
309 elif path.startswith('branches/'): | |
310 elts = path.split('/') | |
311 test = '/'.join(elts[:2]) | |
312 path = '/'.join(elts[2:]) | |
291 else: | 313 else: |
292 path = test.split('/')[-1] | 314 path = test.split('/')[-1] |
293 test = '/'.join(test.split('/')[:-1]) | 315 test = '/'.join(test.split('/')[:-1]) |
294 return path, self._localname(test), test | 316 ln = self._localname(test) |
317 if ln and ln.startswith('../'): | |
318 return None, None, None | |
319 return path, ln, test | |
295 | 320 |
296 def set_current_rev(self, rev): | 321 def set_current_rev(self, rev): |
297 """Set the revision we're currently converting. | 322 """Set the revision we're currently converting. |
298 """ | 323 """ |
299 self.current_rev = rev | 324 self.current_rev = rev |
356 if inc is None or exc is not None: | 381 if inc is None or exc is not None: |
357 return False | 382 return False |
358 return True | 383 return True |
359 | 384 |
360 def _is_path_valid(self, path): | 385 def _is_path_valid(self, path): |
386 if path is None: | |
387 return False | |
361 subpath = self._split_branch_path(path)[0] | 388 subpath = self._split_branch_path(path)[0] |
362 if subpath is None: | 389 if subpath is None: |
363 return False | 390 return False |
364 return self._is_file_included(subpath) | 391 return self._is_file_included(subpath) |
365 | 392 |
502 continue # case 1 | 529 continue # case 1 |
503 if paths[p].action == 'D': | 530 if paths[p].action == 'D': |
504 # check for case 5 | 531 # check for case 5 |
505 for known in self.branches: | 532 for known in self.branches: |
506 if self._svnpath(known).startswith(p): | 533 if self._svnpath(known).startswith(p): |
507 self.branches_to_delete.add(br) # case 5 | 534 self.branches_to_delete.add(known) # case 5 |
508 added_branches.update(self.__determine_parent_branch(p, paths[p].copyfrom_path, | 535 added_branches.update(self.__determine_parent_branch(p, paths[p].copyfrom_path, |
509 paths[p].copyfrom_rev, revision.revnum)) | 536 paths[p].copyfrom_rev, revision.revnum)) |
510 for t in tags_to_delete: | 537 for t in tags_to_delete: |
511 del self.tags[t] | 538 del self.tags[t] |
512 for br in self.branches_to_delete: | 539 for br in self.branches_to_delete: |
563 # back to a list and sort so we get sane behavior | 590 # back to a list and sort so we get sane behavior |
564 files_to_commit = list(files_to_commit) | 591 files_to_commit = list(files_to_commit) |
565 files_to_commit.sort() | 592 files_to_commit.sort() |
566 branch_batches = {} | 593 branch_batches = {} |
567 rev = self.current_rev | 594 rev = self.current_rev |
568 date = rev.date.replace('T', ' ').replace('Z', '').split('.')[0] | 595 date = self.fixdate(rev.date) |
569 date += ' -0000' | |
570 | 596 |
571 # build up the branches that have files on them | 597 # build up the branches that have files on them |
572 for f in files_to_commit: | 598 for f in files_to_commit: |
573 if not self._is_path_valid(f): | 599 if not self._is_path_valid(f): |
574 continue | 600 continue |
613 | 639 |
614 parents = (self.get_parent_revision(rev.revnum, branch), | 640 parents = (self.get_parent_revision(rev.revnum, branch), |
615 revlog.nullid) | 641 revlog.nullid) |
616 if parents[0] in closed_revs and branch in self.branches_to_delete: | 642 if parents[0] in closed_revs and branch in self.branches_to_delete: |
617 continue | 643 continue |
618 # TODO this needs to be fixed with the new revmap | 644 extra = util.build_extra(rev.revnum, branch, |
619 extra = our_util.build_extra(rev.revnum, branch, | 645 open(self.uuid_file).read(), |
620 open(self.uuid_file).read(), | 646 self.subdir) |
621 self.subdir) | |
622 if branch is not None: | 647 if branch is not None: |
623 if (branch not in self.branches | 648 if (branch not in self.branches |
624 and branch not in self.repo.branchtags()): | 649 and branch not in self.repo.branchtags()): |
625 continue | 650 continue |
626 parent_ctx = self.repo.changectx(parents[0]) | 651 parent_ctx = self.repo.changectx(parents[0]) |
656 filectxfn, | 681 filectxfn, |
657 self.authorforsvnauthor(rev.author), | 682 self.authorforsvnauthor(rev.author), |
658 date, | 683 date, |
659 extra) | 684 extra) |
660 new_hash = self.repo.commitctx(current_ctx) | 685 new_hash = self.repo.commitctx(current_ctx) |
661 our_util.describe_commit(self.ui, new_hash, branch) | 686 util.describe_commit(self.ui, new_hash, branch) |
662 if (rev.revnum, branch) not in self.revmap: | 687 if (rev.revnum, branch) not in self.revmap: |
663 self.add_to_revmap(rev.revnum, branch, new_hash) | 688 self.add_to_revmap(rev.revnum, branch, new_hash) |
664 # now we handle branches that need to be committed without any files | 689 # now we handle branches that need to be committed without any files |
665 for branch in self.commit_branches_empty: | 690 for branch in self.commit_branches_empty: |
666 ha = self.get_parent_revision(rev.revnum, branch) | 691 ha = self.get_parent_revision(rev.revnum, branch) |
669 parent_ctx = self.repo.changectx(ha) | 694 parent_ctx = self.repo.changectx(ha) |
670 def del_all_files(*args): | 695 def del_all_files(*args): |
671 raise IOError | 696 raise IOError |
672 # True here meant nuke all files, shouldn't happen with branch closing | 697 # True here meant nuke all files, shouldn't happen with branch closing |
673 if self.commit_branches_empty[branch]: #pragma: no cover | 698 if self.commit_branches_empty[branch]: #pragma: no cover |
674 raise util.Abort('Empty commit to an open branch attempted. ' | 699 raise hgutil.Abort('Empty commit to an open branch attempted. ' |
675 'Please report this issue.') | 700 'Please report this issue.') |
676 extra = our_util.build_extra(rev.revnum, branch, | 701 extra = util.build_extra(rev.revnum, branch, |
677 open(self.uuid_file).read(), | 702 open(self.uuid_file).read(), |
678 self.subdir) | 703 self.subdir) |
679 current_ctx = context.memctx(self.repo, | 704 current_ctx = context.memctx(self.repo, |
680 (ha, node.nullid), | 705 (ha, node.nullid), |
681 rev.message or ' ', | 706 rev.message or ' ', |
683 del_all_files, | 708 del_all_files, |
684 self.authorforsvnauthor(rev.author), | 709 self.authorforsvnauthor(rev.author), |
685 date, | 710 date, |
686 extra) | 711 extra) |
687 new_hash = self.repo.commitctx(current_ctx) | 712 new_hash = self.repo.commitctx(current_ctx) |
688 our_util.describe_commit(self.ui, new_hash, branch) | 713 util.describe_commit(self.ui, new_hash, branch) |
689 if (rev.revnum, branch) not in self.revmap: | 714 if (rev.revnum, branch) not in self.revmap: |
690 self.add_to_revmap(rev.revnum, branch, new_hash) | 715 self.add_to_revmap(rev.revnum, branch, new_hash) |
691 self._save_metadata() | 716 self._save_metadata() |
692 self.clear_current_info() | 717 self.clear_current_info() |
693 | 718 |
694 def authorforsvnauthor(self, author): | 719 def authorforsvnauthor(self, author): |
695 if(author in self.authors): | 720 if author in self.authors: |
696 return self.authors[author] | 721 return self.authors[author] |
697 return '%s%s' %(author, self.author_host) | 722 return '%s%s' % (author, self.author_host) |
698 | 723 |
699 def svnauthorforauthor(self, author): | 724 def svnauthorforauthor(self, author): |
700 for svnauthor, hgauthor in self.authors.iteritems(): | 725 for svnauthor, hgauthor in self.authors.iteritems(): |
701 if author == hgauthor: | 726 if author == hgauthor: |
702 return svnauthor | 727 return svnauthor |
703 else: | 728 else: |
704 # Mercurial incorrectly splits at e.g. '.', so we roll our own. | 729 # return the original svn-side author |
705 return author.rsplit('@', 1)[0] | 730 return author.rsplit('@', 1)[0] |
706 | 731 |
707 def readauthors(self, authorfile): | 732 def readauthors(self, authorfile): |
708 self.ui.note(('Reading authormap from %s\n') % authorfile) | 733 self.ui.note(('Reading authormap from %s\n') % authorfile) |
709 f = open(authorfile, 'r') | 734 f = open(authorfile, 'r') |
835 if br_path != '': | 860 if br_path != '': |
836 br_path2 = br_path + '/' | 861 br_path2 = br_path + '/' |
837 # assuming it is a directory | 862 # assuming it is a directory |
838 self.externals[path] = None | 863 self.externals[path] = None |
839 map(self.delete_file, [pat for pat in self.current_files.iterkeys() | 864 map(self.delete_file, [pat for pat in self.current_files.iterkeys() |
840 if pat.startswith(path)]) | 865 if pat.startswith(path+'/')]) |
841 for f in ctx.walk(our_util.PrefixMatch(br_path2)): | 866 for f in ctx.walk(util.PrefixMatch(br_path2)): |
842 f_p = '%s/%s' % (path, f[len(br_path2):]) | 867 f_p = '%s/%s' % (path, f[len(br_path2):]) |
843 if f_p not in self.current_files: | 868 if f_p not in self.current_files: |
844 self.delete_file(f_p) | 869 self.delete_file(f_p) |
845 self.delete_file(path) | 870 self.delete_file(path) |
846 delete_entry = stash_exception_on_self(delete_entry) | 871 delete_entry = stash_exception_on_self(delete_entry) |
847 | 872 |
848 def open_file(self, path, parent_baton, base_revision, p=None): | 873 def open_file(self, path, parent_baton, base_revision, p=None): |
849 self.current_file = 'foobaz' | 874 self.current_file = None |
850 fpath, branch = self._path_and_branch_for_path(path) | 875 fpath, branch = self._path_and_branch_for_path(path) |
851 if fpath: | 876 if fpath: |
852 self.current_file = path | 877 self.current_file = path |
853 self.ui.note('M %s\n' % path) | 878 self.ui.note('M %s\n' % path) |
854 if base_revision != -1: | 879 if base_revision != -1: |
889 # parentctx is not an ancestor of childctx, files are unrelated | 914 # parentctx is not an ancestor of childctx, files are unrelated |
890 return False | 915 return False |
891 | 916 |
892 def add_file(self, path, parent_baton=None, copyfrom_path=None, | 917 def add_file(self, path, parent_baton=None, copyfrom_path=None, |
893 copyfrom_revision=None, file_pool=None): | 918 copyfrom_revision=None, file_pool=None): |
894 self.current_file = 'foobaz' | 919 self.current_file = None |
895 self.base_revision = None | 920 self.base_revision = None |
896 if path in self.deleted_files: | 921 if path in self.deleted_files: |
897 del self.deleted_files[path] | 922 del self.deleted_files[path] |
898 fpath, branch = self._path_and_branch_for_path(path, existing=False) | 923 fpath, branch = self._path_and_branch_for_path(path, existing=False) |
899 if not fpath: | 924 if not fpath: |
951 cp_f = '' | 976 cp_f = '' |
952 else: | 977 else: |
953 source_rev = copyfrom_revision | 978 source_rev = copyfrom_revision |
954 cp_f, source_branch = self._path_and_branch_for_path(copyfrom_path) | 979 cp_f, source_branch = self._path_and_branch_for_path(copyfrom_path) |
955 if cp_f == '' and br_path == '': | 980 if cp_f == '' and br_path == '': |
981 assert br_path is not None | |
956 self.branches[branch] = source_branch, source_rev, self.current_rev.revnum | 982 self.branches[branch] = source_branch, source_rev, self.current_rev.revnum |
957 new_hash = self.get_parent_revision(source_rev + 1, | 983 new_hash = self.get_parent_revision(source_rev + 1, |
958 source_branch) | 984 source_branch) |
959 if new_hash == node.nullid: | 985 if new_hash == node.nullid: |
960 self.missing_plaintexts.add('%s/' % path) | 986 self.missing_plaintexts.add('%s/' % path) |
1034 target = cStringIO.StringIO() | 1060 target = cStringIO.StringIO() |
1035 self.stream = target | 1061 self.stream = target |
1036 | 1062 |
1037 handler, baton = delta.svn_txdelta_apply(source, target, None) | 1063 handler, baton = delta.svn_txdelta_apply(source, target, None) |
1038 if not callable(handler): #pragma: no cover | 1064 if not callable(handler): #pragma: no cover |
1039 raise util.Abort('Error in Subversion bindings: ' | 1065 raise hgutil.Abort('Error in Subversion bindings: ' |
1040 'cannot call handler!') | 1066 'cannot call handler!') |
1041 def txdelt_window(window): | 1067 def txdelt_window(window): |
1042 try: | 1068 try: |
1043 if not self._is_path_valid(self.current_file): | 1069 if not self._is_path_valid(self.current_file): |
1044 return | 1070 return |
1045 handler(window, baton) | 1071 handler(window, baton) |
1048 self.current_files[self.current_file] = target.getvalue() | 1074 self.current_files[self.current_file] = target.getvalue() |
1049 except core.SubversionException, e: #pragma: no cover | 1075 except core.SubversionException, e: #pragma: no cover |
1050 if e.apr_err == core.SVN_ERR_INCOMPLETE_DATA: | 1076 if e.apr_err == core.SVN_ERR_INCOMPLETE_DATA: |
1051 self.missing_plaintexts.add(self.current_file) | 1077 self.missing_plaintexts.add(self.current_file) |
1052 else: #pragma: no cover | 1078 else: #pragma: no cover |
1053 raise util.Abort(*e.args) | 1079 raise hgutil.Abort(*e.args) |
1054 except: #pragma: no cover | 1080 except: #pragma: no cover |
1055 print len(base), self.current_file | 1081 print len(base), self.current_file |
1056 self._exception_info = sys.exc_info() | 1082 self._exception_info = sys.exc_info() |
1057 raise | 1083 raise |
1058 return txdelt_window | 1084 return txdelt_window |