Faster append-only revmap implementation.

This commit is contained in:
Andreas Hartmetz 2008-10-15 21:47:48 -04:00
parent b168704b66
commit 4430556e43
3 changed files with 33 additions and 10 deletions

View File

@ -440,7 +440,7 @@ def stupid_svn_server_pull_rev(ui, svn, hg_editor, r):
date, date,
extra) extra)
ha = hg_editor.repo.commitctx(current_ctx) ha = hg_editor.repo.commitctx(current_ctx)
hg_editor.revmap[r.revnum, b] = ha hg_editor.add_to_revmap(r.revnum, b, ha)
hg_editor._save_metadata() hg_editor._save_metadata()
ui.status('committed as %s on branch %s\n' % ui.status('committed as %s on branch %s\n' %
(node.hex(ha), b or 'default')) (node.hex(ha), b or 'default'))

View File

@ -49,6 +49,13 @@ def stash_exception_on_self(fn):
class HgChangeReceiver(delta.Editor): class HgChangeReceiver(delta.Editor):
def add_to_revmap(self, revnum, branch, node_hash):
f = open(self.revmap_file, 'a')
f.write(str(revnum) + ' ' + node.hex(node_hash) + ' ' + (branch or '') + '\n')
f.flush()
f.close()
self.revmap[revnum, branch] = node_hash
def __init__(self, path, ui_=None, subdir='', author_host='', def __init__(self, path, ui_=None, subdir='', author_host='',
tag_locations=['tags']): tag_locations=['tags']):
"""path is the path to the target hg repo. """path is the path to the target hg repo.
@ -67,7 +74,13 @@ class HgChangeReceiver(delta.Editor):
self.revmap = {} self.revmap = {}
if os.path.exists(self.revmap_file): if os.path.exists(self.revmap_file):
f = open(self.revmap_file) f = open(self.revmap_file)
self.revmap = pickle.load(f) for l in f:
revnum, node_hash, branch = l.split(' ', 2)
if branch == '\n':
branch = None
else:
branch = branch[:-1]
self.revmap[int(revnum), branch] = node.bin(node_hash)
f.close() f.close()
self.branches = {} self.branches = {}
if os.path.exists(self.branch_info_file): if os.path.exists(self.branch_info_file):
@ -106,6 +119,7 @@ class HgChangeReceiver(delta.Editor):
else: else:
self.repo = hg.repository(self.ui, repo_path, create=True) self.repo = hg.repository(self.ui, repo_path, create=True)
os.makedirs(os.path.dirname(self.uuid_file)) os.makedirs(os.path.dirname(self.uuid_file))
open(self.revmap_file, 'w') # make empty file
def clear_current_info(self): def clear_current_info(self):
'''Clear the info relevant to a replayed revision so that the next '''Clear the info relevant to a replayed revision so that the next
@ -124,7 +138,6 @@ class HgChangeReceiver(delta.Editor):
'''Save the Subversion metadata. This should really be called after '''Save the Subversion metadata. This should really be called after
every revision is created. every revision is created.
''' '''
pickle_atomic(self.revmap, self.revmap_file, self.meta_data_dir)
pickle_atomic(self.branches, self.branch_info_file, self.meta_data_dir) pickle_atomic(self.branches, self.branch_info_file, self.meta_data_dir)
pickle_atomic(self.tags, self.tag_info_file, self.meta_data_dir) pickle_atomic(self.tags, self.tag_info_file, self.meta_data_dir)
@ -373,8 +386,7 @@ class HgChangeReceiver(delta.Editor):
self.ui.status('committed as %s on branch %s\n' % self.ui.status('committed as %s on branch %s\n' %
(node.hex(new_hash), (branch or 'default'))) (node.hex(new_hash), (branch or 'default')))
if (rev.revnum, branch) not in self.revmap: if (rev.revnum, branch) not in self.revmap:
self.revmap[rev.revnum, branch] = new_hash self.add_to_revmap(rev.revnum, branch, new_hash)
self._save_metadata()
# now we handle branches that need to be committed without any files # now we handle branches that need to be committed without any files
for branch in self.commit_branches_empty: for branch in self.commit_branches_empty:
ha = self.get_parent_revision(rev.revnum, branch) ha = self.get_parent_revision(rev.revnum, branch)
@ -403,8 +415,7 @@ class HgChangeReceiver(delta.Editor):
self.ui.status('committed as %s on branch %s\n' % self.ui.status('committed as %s on branch %s\n' %
(node.hex(new_hash), (branch or 'default'))) (node.hex(new_hash), (branch or 'default')))
if (rev.revnum, branch) not in self.revmap: if (rev.revnum, branch) not in self.revmap:
self.revmap[rev.revnum, branch] = new_hash self.add_to_revmap(rev.revnum, branch, new_hash)
self._save_metadata()
self.clear_current_info() self.clear_current_info()
@property @property

View File

@ -64,6 +64,19 @@ def generate_hg_tags(ui, hg_repo_path, **opts):
source_ha = hg_editor.get_parent_revision(source[1]+1, source[0]) source_ha = hg_editor.get_parent_revision(source[1]+1, source[0])
f.write('%s tag/%s\n' % (node.hex(source_ha), tag)) f.write('%s tag/%s\n' % (node.hex(source_ha), tag))
def parse_revmap(revmap_filename):
revmap = {}
f = open(revmap_filename)
for l in f:
revnum, node_hash, branch = l.split(' ', 2)
if branch == '\n':
branch = None
else:
branch = branch[:-1]
revmap[int(revnum), branch] = node.bin(node_hash)
f.close()
return revmap
@register_subcommand('up') @register_subcommand('up')
def update(ui, args, repo, clean=False, **opts): def update(ui, args, repo, clean=False, **opts):
"""Update to a specified Subversion revision number. """Update to a specified Subversion revision number.
@ -72,7 +85,7 @@ def update(ui, args, repo, clean=False, **opts):
rev = int(args[0]) rev = int(args[0])
path = os.path.join(repo.path, 'svn', 'rev_map') path = os.path.join(repo.path, 'svn', 'rev_map')
answers = [] answers = []
for k,v in pickle.load(open(path)).iteritems(): for k,v in parse_revmap(path).iteritems():
if k[0] == rev: if k[0] == rev:
answers.append((v, k[1])) answers.append((v, k[1]))
if len(answers) == 1: if len(answers) == 1:
@ -139,8 +152,7 @@ def verify_all_revisions(ui, args, repo, **opts):
args = list(args) args = list(args)
if args: if args:
start_rev = int(args.pop(0)) start_rev = int(args.pop(0))
revmap_f = open(os.path.join(repo.path, 'svn', 'rev_map')) revmap = parse_revmap(os.path.join(repo.path, 'svn', 'rev_map'))
revmap = pickle.load(revmap_f)
revs = sorted(revmap.keys()) revs = sorted(revmap.keys())
for revnum, br in revs: for revnum, br in revs:
if revnum < start_rev: if revnum < start_rev: