Mercurial > hgsubversion
comparison hg_delta_editor.py @ 33:a9c15cae50e5
Faster append-only revmap implementation.
author | Andreas Hartmetz <ahartmetz@gmail.com> |
---|---|
date | Wed, 15 Oct 2008 21:47:48 -0400 |
parents | 1f8854804795 |
children | 50d55c3e0d85 |
comparison
equal
deleted
inserted
replaced
32:d01196ca1e39 | 33:a9c15cae50e5 |
---|---|
47 raise | 47 raise |
48 return fun | 48 return fun |
49 | 49 |
50 | 50 |
51 class HgChangeReceiver(delta.Editor): | 51 class HgChangeReceiver(delta.Editor): |
52 def add_to_revmap(self, revnum, branch, node_hash): | |
53 f = open(self.revmap_file, 'a') | |
54 f.write(str(revnum) + ' ' + node.hex(node_hash) + ' ' + (branch or '') + '\n') | |
55 f.flush() | |
56 f.close() | |
57 self.revmap[revnum, branch] = node_hash | |
58 | |
52 def __init__(self, path, ui_=None, subdir='', author_host='', | 59 def __init__(self, path, ui_=None, subdir='', author_host='', |
53 tag_locations=['tags']): | 60 tag_locations=['tags']): |
54 """path is the path to the target hg repo. | 61 """path is the path to the target hg repo. |
55 | 62 |
56 subdir is the subdirectory of the edits *on the svn server*. | 63 subdir is the subdirectory of the edits *on the svn server*. |
65 if self.subdir and self.subdir[0] == '/': | 72 if self.subdir and self.subdir[0] == '/': |
66 self.subdir = self.subdir[1:] | 73 self.subdir = self.subdir[1:] |
67 self.revmap = {} | 74 self.revmap = {} |
68 if os.path.exists(self.revmap_file): | 75 if os.path.exists(self.revmap_file): |
69 f = open(self.revmap_file) | 76 f = open(self.revmap_file) |
70 self.revmap = pickle.load(f) | 77 for l in f: |
78 revnum, node_hash, branch = l.split(' ', 2) | |
79 if branch == '\n': | |
80 branch = None | |
81 else: | |
82 branch = branch[:-1] | |
83 self.revmap[int(revnum), branch] = node.bin(node_hash) | |
71 f.close() | 84 f.close() |
72 self.branches = {} | 85 self.branches = {} |
73 if os.path.exists(self.branch_info_file): | 86 if os.path.exists(self.branch_info_file): |
74 f = open(self.branch_info_file) | 87 f = open(self.branch_info_file) |
75 self.branches = pickle.load(f) | 88 self.branches = pickle.load(f) |
104 assert os.path.isfile(self.uuid_file) | 117 assert os.path.isfile(self.uuid_file) |
105 assert os.path.isfile(self.last_revision_handled_file) | 118 assert os.path.isfile(self.last_revision_handled_file) |
106 else: | 119 else: |
107 self.repo = hg.repository(self.ui, repo_path, create=True) | 120 self.repo = hg.repository(self.ui, repo_path, create=True) |
108 os.makedirs(os.path.dirname(self.uuid_file)) | 121 os.makedirs(os.path.dirname(self.uuid_file)) |
122 open(self.revmap_file, 'w') # make empty file | |
109 | 123 |
110 def clear_current_info(self): | 124 def clear_current_info(self): |
111 '''Clear the info relevant to a replayed revision so that the next | 125 '''Clear the info relevant to a replayed revision so that the next |
112 revision can be replayed. | 126 revision can be replayed. |
113 ''' | 127 ''' |
122 | 136 |
123 def _save_metadata(self): | 137 def _save_metadata(self): |
124 '''Save the Subversion metadata. This should really be called after | 138 '''Save the Subversion metadata. This should really be called after |
125 every revision is created. | 139 every revision is created. |
126 ''' | 140 ''' |
127 pickle_atomic(self.revmap, self.revmap_file, self.meta_data_dir) | |
128 pickle_atomic(self.branches, self.branch_info_file, self.meta_data_dir) | 141 pickle_atomic(self.branches, self.branch_info_file, self.meta_data_dir) |
129 pickle_atomic(self.tags, self.tag_info_file, self.meta_data_dir) | 142 pickle_atomic(self.tags, self.tag_info_file, self.meta_data_dir) |
130 | 143 |
131 def branches_in_paths(self, paths): | 144 def branches_in_paths(self, paths): |
132 '''Given a list of paths, return the set of branches that are touched. | 145 '''Given a list of paths, return the set of branches that are touched. |
371 extra) | 384 extra) |
372 new_hash = self.repo.commitctx(current_ctx) | 385 new_hash = self.repo.commitctx(current_ctx) |
373 self.ui.status('committed as %s on branch %s\n' % | 386 self.ui.status('committed as %s on branch %s\n' % |
374 (node.hex(new_hash), (branch or 'default'))) | 387 (node.hex(new_hash), (branch or 'default'))) |
375 if (rev.revnum, branch) not in self.revmap: | 388 if (rev.revnum, branch) not in self.revmap: |
376 self.revmap[rev.revnum, branch] = new_hash | 389 self.add_to_revmap(rev.revnum, branch, new_hash) |
377 self._save_metadata() | |
378 # now we handle branches that need to be committed without any files | 390 # now we handle branches that need to be committed without any files |
379 for branch in self.commit_branches_empty: | 391 for branch in self.commit_branches_empty: |
380 ha = self.get_parent_revision(rev.revnum, branch) | 392 ha = self.get_parent_revision(rev.revnum, branch) |
381 if ha == node.nullid: | 393 if ha == node.nullid: |
382 continue | 394 continue |
401 extra) | 413 extra) |
402 new_hash = self.repo.commitctx(current_ctx) | 414 new_hash = self.repo.commitctx(current_ctx) |
403 self.ui.status('committed as %s on branch %s\n' % | 415 self.ui.status('committed as %s on branch %s\n' % |
404 (node.hex(new_hash), (branch or 'default'))) | 416 (node.hex(new_hash), (branch or 'default'))) |
405 if (rev.revnum, branch) not in self.revmap: | 417 if (rev.revnum, branch) not in self.revmap: |
406 self.revmap[rev.revnum, branch] = new_hash | 418 self.add_to_revmap(rev.revnum, branch, new_hash) |
407 self._save_metadata() | |
408 self.clear_current_info() | 419 self.clear_current_info() |
409 | 420 |
410 @property | 421 @property |
411 def meta_data_dir(self): | 422 def meta_data_dir(self): |
412 return os.path.join(self.path, '.hg', 'svn') | 423 return os.path.join(self.path, '.hg', 'svn') |