Mercurial > hgsubversion
diff hgsubversion/hg_delta_editor.py @ 414:343da842dbe6
split parts of HgChangeReceiver out into an SVNMeta class
Less obvious things:
- my reordering in the previous was incomplete
- _branch_for_path() was unused, so I removed it
- _svnpath() was removed in favor of identical _remotename()
- I've checked "no cover" bits manually
author | Dirkjan Ochtman <dirkjan@ochtman.nl> |
---|---|
date | Thu, 11 Jun 2009 18:56:35 +0200 |
parents | ac0cc3c9ea63 |
children | b17b2969861c |
line wrap: on
line diff
--- a/hgsubversion/hg_delta_editor.py +++ b/hgsubversion/hg_delta_editor.py @@ -1,23 +1,17 @@ import cStringIO -import cPickle as pickle -import os import sys -import tempfile import traceback from mercurial import context -from mercurial import hg -from mercurial import ui from mercurial import util as hgutil from mercurial import revlog from mercurial import node -from mercurial import error from svn import delta from svn import core +import svnmeta import svnexternals import util -import maps class MissingPlainTextError(Exception): """Exception raised when the repo lacks a source file required for replaying @@ -29,22 +23,6 @@ class ReplayException(Exception): exception. """ -def pickle_atomic(data, file_path, dir=None): - """pickle some data to a path atomically. - - This is present because I kept corrupting my revmap by managing to hit ^C - during the pickle of that file. - """ - try: - f, path = tempfile.mkstemp(prefix='pickling', dir=dir) - f = os.fdopen(f, 'w') - pickle.dump(data, f) - f.close() - except: #pragma: no cover - raise - else: - hgutil.rename(path, file_path) - def ieditor(fn): """Helps identify methods used by the SVN editor interface. @@ -69,8 +47,7 @@ class RevisionData(object): __slots__ = [ 'file', 'files', 'deleted', 'rev', 'execfiles', 'symlinks', 'batons', - 'copies', 'missing', 'emptybranches', 'base', 'closebranches', - 'externals', + 'copies', 'missing', 'emptybranches', 'base', 'externals', ] def __init__(self): @@ -89,431 +66,16 @@ class RevisionData(object): self.missing = set() self.emptybranches = {} self.base = None - self.closebranches = set() self.externals = {} class HgChangeReceiver(delta.Editor): def __init__(self, repo, uuid=None, subdir=''): - """path is the path to the target hg repo. - - subdir is the subdirectory of the edits *on the svn server*. - It is needed for stripping paths off in certain cases. - """ self.ui = repo.ui self.repo = repo - self.path = os.path.normpath(repo.join('..')) - - if not os.path.isdir(self.meta_data_dir): - os.makedirs(self.meta_data_dir) - self._set_uuid(uuid) - # TODO: validate subdir too - self.revmap = maps.RevMap(repo) - - author_host = self.ui.config('hgsubversion', 'defaulthost', uuid) - authors = self.ui.config('hgsubversion', 'authormap') - tag_locations = self.ui.configlist('hgsubversion', 'tagpaths', ['tags']) - self.usebranchnames = self.ui.configbool('hgsubversion', - 'usebranchnames', True) - - # FIXME: test that this hasn't changed! defer & compare? - self.subdir = subdir - if self.subdir and self.subdir[0] == '/': - self.subdir = self.subdir[1:] - self.branches = {} - if os.path.exists(self.branch_info_file): - f = open(self.branch_info_file) - self.branches = pickle.load(f) - f.close() - self.tags = {} - if os.path.exists(self.tag_locations_file): - f = open(self.tag_locations_file) - self.tag_locations = pickle.load(f) - f.close() - else: - self.tag_locations = tag_locations - pickle_atomic(self.tag_locations, self.tag_locations_file, - self.meta_data_dir) - # ensure nested paths are handled properly - self.tag_locations.sort() - self.tag_locations.reverse() - + self.meta = svnmeta.SVNMeta(repo, uuid, subdir) self.current = RevisionData() - self.authors = maps.AuthorMap(self.ui, self.authors_file, - defaulthost=author_host) - if authors: self.authors.load(authors) - - self.lastdate = '1970-01-01 00:00:00 -0000' - self.filemap = maps.FileMap(repo) - - def _get_uuid(self): - return open(os.path.join(self.meta_data_dir, 'uuid')).read() - - def _set_uuid(self, uuid): - if not uuid: - return - elif os.path.isfile(os.path.join(self.meta_data_dir, 'uuid')): - stored_uuid = self._get_uuid() - assert stored_uuid - if uuid != stored_uuid: - raise hgutil.Abort('unable to operate on unrelated repository') - else: - if uuid: - f = open(os.path.join(self.meta_data_dir, 'uuid'), 'w') - f.write(uuid) - f.flush() - f.close() - else: - raise hgutil.Abort('unable to operate on unrelated repository') - - uuid = property(_get_uuid, _set_uuid, None, - 'Error-checked UUID of source Subversion repository.') - - @property - def meta_data_dir(self): - return os.path.join(self.path, '.hg', 'svn') - - @property - def branch_info_file(self): - return os.path.join(self.meta_data_dir, 'branch_info') - - @property - def tag_locations_file(self): - return os.path.join(self.meta_data_dir, 'tag_locations') - - @property - def authors_file(self): - return os.path.join(self.meta_data_dir, 'authors') - - def hashes(self): - return dict((v, k) for (k, v) in self.revmap.iteritems()) - - def branchedits(self, branch, rev): - check = lambda x: x[0][1] == branch and x[0][0] < rev.revnum - return sorted(filter(check, self.revmap.iteritems()), reverse=True) - - def last_known_revision(self): - """Obtain the highest numbered -- i.e. latest -- revision known. - - Currently, this function just iterates over the entire revision map - using the max() builtin. This may be slow for extremely large - repositories, but for now, it's fast enough. - """ - try: - return max(k[0] for k in self.revmap.iterkeys()) - except ValueError: - return 0 - - def fixdate(self, date): - if date is not None: - date = date.replace('T', ' ').replace('Z', '').split('.')[0] - date += ' -0000' - self.lastdate = date - else: - date = self.lastdate - return date - - def _save_metadata(self): - '''Save the Subversion metadata. This should really be called after - every revision is created. - ''' - pickle_atomic(self.branches, self.branch_info_file, self.meta_data_dir) - - def _localname(self, path): - """Compute the local name for a branch located at path. - """ - assert not path.startswith('tags/') - if path == 'trunk': - return None - elif path.startswith('branches/'): - return path[len('branches/'):] - return '../%s' % path - - def _remotename(self, branch): - if branch == 'default' or branch is None: - return 'trunk' - elif branch.startswith('../'): - return branch[3:] - return 'branches/%s' % branch - - def _normalize_path(self, path): - '''Normalize a path to strip of leading slashes and our subdir if we - have one. - ''' - if path and path[0] == '/': - path = path[1:] - if path and path.startswith(self.subdir): - path = path[len(self.subdir):] - if path and path[0] == '/': - path = path[1:] - return path - - def _is_path_tag(self, path): - """If path could represent the path to a tag, returns the potential tag - name. Otherwise, returns False. - - Note that it's only a tag if it was copied from the path '' in a branch - (or tag) we have, for our purposes. - """ - path = self._normalize_path(path) - for tagspath in self.tag_locations: - onpath = path.startswith(tagspath) - longer = len(path) > len('%s/' % tagspath) - if path and onpath and longer: - tag, subpath = path[len(tagspath) + 1:], '' - return tag - return False - - def _split_branch_path(self, path, existing=True): - """Figure out which branch inside our repo this path represents, and - also figure out which path inside that branch it is. - - Returns a tuple of (path within branch, local branch name, server-side branch path). - - If existing=True, will return None, None, None if the file isn't on some known - branch. If existing=False, then it will guess what the branch would be if it were - known. - """ - path = self._normalize_path(path) - if path.startswith('tags/'): - return None, None, None - test = '' - path_comps = path.split('/') - while self._localname(test) not in self.branches and len(path_comps): - if not test: - test = path_comps.pop(0) - else: - test += '/%s' % path_comps.pop(0) - if self._localname(test) in self.branches: - return path[len(test)+1:], self._localname(test), test - if existing: - return None, None, None - if path == 'trunk' or path.startswith('trunk/'): - path = path.split('/')[1:] - test = 'trunk' - elif path.startswith('branches/'): - elts = path.split('/') - test = '/'.join(elts[:2]) - path = '/'.join(elts[2:]) - else: - path = test.split('/')[-1] - test = '/'.join(test.split('/')[:-1]) - ln = self._localname(test) - if ln and ln.startswith('../'): - return None, None, None - return path, ln, test - - def _is_path_valid(self, path): - if path is None: - return False - subpath = self._split_branch_path(path)[0] - if subpath is None: - return False - return subpath in self.filemap - - def get_parent_svn_branch_and_rev(self, number, branch): - number -= 1 - if (number, branch) in self.revmap: - return number, branch - real_num = 0 - for num, br in self.revmap.iterkeys(): - if br != branch: - continue - if num <= number and num > real_num: - real_num = num - if branch in self.branches: - parent_branch = self.branches[branch][0] - parent_branch_rev = self.branches[branch][1] - # check to see if this branch already existed and is the same - if parent_branch_rev < real_num: - return real_num, branch - # if that wasn't true, then this is the a new branch with the - # same name as some old deleted branch - if parent_branch_rev <= 0 and real_num == 0: - return None, None - branch_created_rev = self.branches[branch][2] - if parent_branch == 'trunk': - parent_branch = None - if branch_created_rev <= number+1 and branch != parent_branch: - return self.get_parent_svn_branch_and_rev( - parent_branch_rev+1, - parent_branch) - if real_num != 0: - return real_num, branch - return None, None - - def get_parent_revision(self, number, branch): - '''Get the parent revision hash for a commit on a specific branch. - ''' - r, br = self.get_parent_svn_branch_and_rev(number, branch) - if r is not None: - return self.revmap[r, br] - return revlog.nullid - - def update_branch_tag_map_for_rev(self, revision): - paths = revision.paths - added_branches = {} - added_tags = {} - self.current.closebranches = set() - tags_to_delete = set() - for p in sorted(paths): - t_name = self._is_path_tag(p) - if t_name != False: - src_p, src_rev = paths[p].copyfrom_path, paths[p].copyfrom_rev - # if you commit to a tag, I'm calling you stupid and ignoring - # you. - if src_p is not None and src_rev is not None: - file, branch = self._path_and_branch_for_path(src_p) - if file is None: - # some crazy people make tags from other tags - file = '' - from_tag = self._is_path_tag(src_p) - if not from_tag: - continue - branch, src_rev = self.tags[from_tag] - if t_name not in added_tags and file is '': - added_tags[t_name] = branch, src_rev - elif file: - t_name = t_name[:-(len(file)+1)] - if src_rev > added_tags[t_name][1]: - added_tags[t_name] = branch, src_rev - elif (paths[p].action == 'D' and p.endswith(t_name) - and t_name in self.tags): - tags_to_delete.add(t_name) - continue - # At this point we know the path is not a tag. In that - # case, we only care if it is the root of a new branch (in - # this function). This is determined by the following - # checks: - # 1. Is the file located inside any currently known - # branch? If yes, then we're done with it, this isn't - # interesting. - # 2. Does the file have copyfrom information? If yes, then - # we're done: this is a new branch, and we record the - # copyfrom in added_branches if it comes from the root - # of another branch, or create it from scratch. - # 3. Neither of the above. This could be a branch, but it - # might never work out for us. It's only ever a branch - # (as far as we're concerned) if it gets committed to, - # which we have to detect at file-write time anyway. So - # we do nothing here. - # 4. It's the root of an already-known branch, with an - # action of 'D'. We mark the branch as deleted. - # 5. It's the parent directory of one or more - # already-known branches, so we mark them as deleted. - # 6. It's a branch being replaced by another branch - the - # action will be 'R'. - fi, br = self._path_and_branch_for_path(p) - if fi is not None: - if fi == '': - if paths[p].action == 'D': - self.current.closebranches.add(br) # case 4 - elif paths[p].action == 'R': - parent = self._determine_parent_branch( - p, paths[p].copyfrom_path, paths[p].copyfrom_rev, - revision.revnum) - added_branches.update(parent) - continue # case 1 - if paths[p].action == 'D': - for known in self.branches: - if self._svnpath(known).startswith(p): - self.current.closebranches.add(known) # case 5 - parent = self._determine_parent_branch( - p, paths[p].copyfrom_path, paths[p].copyfrom_rev, revision.revnum) - if not parent and paths[p].copyfrom_path: - bpath, branch = self._path_and_branch_for_path(p, False) - if (bpath is not None - and branch not in self.branches - and branch not in added_branches): - parent = {branch: (None, 0, revision.revnum)} - added_branches.update(parent) - rmtags = dict((t, self.tags[t][0]) for t in tags_to_delete) - return { - 'tags': (added_tags, rmtags), - 'branches': (added_branches, self.current.closebranches), - } - - def save_tbdelta(self, tbdelta): - for t in tbdelta['tags'][1]: - del self.tags[t] - for br in tbdelta['branches'][1]: - del self.branches[br] - for t, info in tbdelta['tags'][0].items(): - self.ui.status('Tagged %s@%s as %s\n' % - (info[0] or 'trunk', info[1], t)) - self.tags.update(tbdelta['tags'][0]) - self.branches.update(tbdelta['branches'][0]) - - def committags(self, delta, rev, endbranches): - - date = self.fixdate(rev.date) - # determine additions/deletions per branch - branches = {} - for tag, source in delta[0].iteritems(): - b, r = source - branches.setdefault(b, []).append(('add', tag, r)) - for tag, branch in delta[1].iteritems(): - branches.setdefault(branch, []).append(('rm', tag, None)) - - for b, tags in branches.iteritems(): - - # modify parent's .hgtags source - parent = self.repo[self.get_parent_revision(rev.revnum, b)] - if '.hgtags' not in parent: - src = '' - else: - src = parent['.hgtags'].data() - for op, tag, r in sorted(tags, reverse=True): - if op == 'add': - tagged = node.hex(self.revmap[ - self.get_parent_svn_branch_and_rev(r+1, b)]) - elif op == 'rm': - tagged = node.hex(node.nullid) - src += '%s %s\n' % (tagged, tag) - - # add new changeset containing updated .hgtags - def fctxfun(repo, memctx, path): - return context.memfilectx(path='.hgtags', data=src, - islink=False, isexec=False, - copied=None) - extra = util.build_extra(rev.revnum, b, self.uuid, self.subdir) - if not self.usebranchnames: - extra.pop('branch', None) - if b in endbranches: - extra['close'] = 1 - ctx = context.memctx(self.repo, - (parent.node(), node.nullid), - rev.message or ' ', - ['.hgtags'], - fctxfun, - self.authors[rev.author], - date, - extra) - new = self.repo.commitctx(ctx) - if (rev.revnum, b) not in self.revmap: - self.revmap[rev.revnum, b] = new - if b in endbranches: - endbranches.pop(b) - bname = b or 'default' - self.ui.status('Marked branch %s as closed.\n' % bname) - - def delbranch(self, branch, node, rev): - pctx = self.repo[node] - files = pctx.manifest().keys() - extra = {'close': 1} - if self.usebranchnames: - extra['branch'] = branch or 'default' - ctx = context.memctx(self.repo, - (node, revlog.nullid), - rev.message or util.default_commit_msg, - [], - lambda x, y, z: None, - self.authors[rev.author], - self.fixdate(rev.date), - extra) - new = self.repo.commitctx(ctx) - self.ui.status('Marked branch %s as closed.\n' % (branch or 'default')) def set_file(self, path, data, isexec=False, islink=False): if islink: @@ -534,34 +96,6 @@ class HgChangeReceiver(delta.Editor): self.current.symlinks[path] = False self.ui.note('D %s\n' % path) - def _svnpath(self, branch): - """Return the relative path in svn of branch. - """ - if branch == None or branch == 'default': - return 'trunk' - elif branch.startswith('../'): - return branch[3:] - return 'branches/%s' % branch - - def _path_and_branch_for_path(self, path, existing=True): - return self._split_branch_path(path, existing=existing)[:2] - - def _branch_for_path(self, path, existing=True): - return self._path_and_branch_for_path(path, existing=existing)[1] - - def _determine_parent_branch(self, p, src_path, src_rev, revnum): - if src_path is not None: - src_file, src_branch = self._path_and_branch_for_path(src_path) - src_tag = self._is_path_tag(src_path) - if src_tag != False: - # also case 2 - src_branch, src_rev = self.tags[src_tag] - return {self._localname(p): (src_branch, src_rev, revnum )} - if src_file == '': - # case 2 - return {self._localname(p): (src_branch, src_rev, revnum )} - return {} - def _updateexternals(self): if not self.current.externals: return @@ -569,13 +103,13 @@ class HgChangeReceiver(delta.Editor): revnum = self.current.rev.revnum branches = {} for path, entry in self.current.externals.iteritems(): - if not self._is_path_valid(path): + if not self.meta._is_path_valid(path): self.ui.warn('WARNING: Invalid path %s in externals\n' % path) continue - p, b, bp = self._split_branch_path(path) + p, b, bp = self.meta._split_branch_path(path) if bp not in branches: external = svnexternals.externalsfile() - parent = self.get_parent_revision(revnum, b) + parent = self.meta.get_parent_revision(revnum, b) pctx = self.repo[parent] if '.hgsvnexternals' in pctx: external.read(pctx['.hgsvnexternals'].data()) @@ -609,20 +143,20 @@ class HgChangeReceiver(delta.Editor): files_to_commit.sort() branch_batches = {} rev = self.current.rev - date = self.fixdate(rev.date) + date = self.meta.fixdate(rev.date) # build up the branches that have files on them for f in files_to_commit: - if not self._is_path_valid(f): + if not self.meta._is_path_valid(f): continue - p, b = self._path_and_branch_for_path(f) + p, b = self.meta._path_and_branch_for_path(f) if b not in branch_batches: branch_batches[b] = [] branch_batches[b].append((p, f)) closebranches = {} for branch in tbdelta['branches'][1]: - branchedits = self.branchedits(branch, rev) + branchedits = self.meta.branchedits(branch, rev) if len(branchedits) < 1: # can't close a branch that never existed continue @@ -636,13 +170,13 @@ class HgChangeReceiver(delta.Editor): del self.current.emptybranches[branch] files = dict(files) - parents = (self.get_parent_revision(rev.revnum, branch), + parents = (self.meta.get_parent_revision(rev.revnum, branch), revlog.nullid) - if parents[0] in closedrevs and branch in self.current.closebranches: + if parents[0] in closedrevs and branch in self.meta.closebranches: continue - extra = util.build_extra(rev.revnum, branch, self.uuid, self.subdir) + extra = util.build_extra(rev.revnum, branch, self.meta.uuid, self.meta.subdir) if branch is not None: - if (branch not in self.branches + if (branch not in self.meta.branches and branch not in self.repo.branchtags()): continue parent_ctx = self.repo.changectx(parents[0]) @@ -673,24 +207,24 @@ class HgChangeReceiver(delta.Editor): data=data, islink=is_link, isexec=is_exec, copied=copied) - if not self.usebranchnames: + if not self.meta.usebranchnames: extra.pop('branch', None) current_ctx = context.memctx(self.repo, parents, rev.message or '...', files.keys(), filectxfn, - self.authors[rev.author], + self.meta.authors[rev.author], date, extra) new_hash = self.repo.commitctx(current_ctx) util.describe_commit(self.ui, new_hash, branch) - if (rev.revnum, branch) not in self.revmap: - self.revmap[rev.revnum, branch] = new_hash + if (rev.revnum, branch) not in self.meta.revmap: + self.meta.revmap[rev.revnum, branch] = new_hash # 2. handle branches that need to be committed without any files for branch in self.current.emptybranches: - ha = self.get_parent_revision(rev.revnum, branch) + ha = self.meta.get_parent_revision(rev.revnum, branch) if ha == node.nullid: continue parent_ctx = self.repo.changectx(ha) @@ -700,44 +234,44 @@ class HgChangeReceiver(delta.Editor): if self.current.emptybranches[branch]: #pragma: no cover raise hgutil.Abort('Empty commit to an open branch attempted. ' 'Please report this issue.') - extra = util.build_extra(rev.revnum, branch, self.uuid, self.subdir) - if not self.usebranchnames: + extra = util.build_extra(rev.revnum, branch, self.meta.uuid, self.meta.subdir) + if not self.meta.usebranchnames: extra.pop('branch', None) current_ctx = context.memctx(self.repo, (ha, node.nullid), rev.message or ' ', [], del_all_files, - self.authors[rev.author], + self.meta.authors[rev.author], date, extra) new_hash = self.repo.commitctx(current_ctx) util.describe_commit(self.ui, new_hash, branch) - if (rev.revnum, branch) not in self.revmap: - self.revmap[rev.revnum, branch] = new_hash + if (rev.revnum, branch) not in self.meta.revmap: + self.meta.revmap[rev.revnum, branch] = new_hash # 3. handle tags if tbdelta['tags'][0] or tbdelta['tags'][1]: - self.committags(tbdelta['tags'], rev, closebranches) + self.meta.committags(tbdelta['tags'], rev, closebranches) # 4. close any branches that need it for branch, parent in closebranches.iteritems(): if parent is None: continue - self.delbranch(branch, parent, rev) + self.meta.delbranch(branch, parent, rev) - self._save_metadata() + self.meta._save_metadata() self.current.clear() # Here come all the actual editor methods @ieditor def delete_entry(self, path, revision_bogus, parent_baton, pool=None): - br_path, branch = self._path_and_branch_for_path(path) + br_path, branch = self.meta._path_and_branch_for_path(path) if br_path == '': - self.current.closebranches.add(branch) + self.meta.closebranches.add(branch) if br_path is not None: - ha = self.get_parent_revision(self.current.rev.revnum, branch) + ha = self.meta.get_parent_revision(self.current.rev.revnum, branch) if ha == revlog.nullid: return ctx = self.repo.changectx(ha) @@ -758,7 +292,7 @@ class HgChangeReceiver(delta.Editor): @ieditor def open_file(self, path, parent_baton, base_revision, p=None): self.current.file = None - fpath, branch = self._path_and_branch_for_path(path) + fpath, branch = self.meta._path_and_branch_for_path(path) if not fpath: self.ui.debug('WARNING: Opening non-existant file %s\n' % path) return @@ -776,10 +310,10 @@ class HgChangeReceiver(delta.Editor): baserev = base_revision if baserev is None or baserev == -1: baserev = self.current.rev.revnum - 1 - parent = self.get_parent_revision(baserev + 1, branch) + parent = self.meta.get_parent_revision(baserev + 1, branch) ctx = self.repo[parent] - if not self._is_path_valid(path): + if not self.meta._is_path_valid(path): return if fpath not in ctx: @@ -798,12 +332,12 @@ class HgChangeReceiver(delta.Editor): self.current.base = None if path in self.current.deleted: del self.current.deleted[path] - fpath, branch = self._path_and_branch_for_path(path, existing=False) + fpath, branch = self.meta._path_and_branch_for_path(path, existing=False) if not fpath: return - if branch not in self.branches: + if branch not in self.meta.branches: # we know this branch will exist now, because it has at least one file. Rock. - self.branches[branch] = None, 0, self.current.rev.revnum + self.meta.branches[branch] = None, 0, self.current.rev.revnum self.current.file = path if not copyfrom_path: self.ui.note('A %s\n' % path) @@ -811,20 +345,20 @@ class HgChangeReceiver(delta.Editor): return self.ui.note('A+ %s\n' % path) (from_file, - from_branch) = self._path_and_branch_for_path(copyfrom_path) + from_branch) = self.meta._path_and_branch_for_path(copyfrom_path) if not from_file: self.current.missing.add(path) return - ha = self.get_parent_revision(copyfrom_revision + 1, - from_branch) + ha = self.meta.get_parent_revision(copyfrom_revision + 1, + from_branch) ctx = self.repo.changectx(ha) if from_file in ctx: fctx = ctx.filectx(from_file) flags = fctx.flags() self.set_file(path, fctx.data(), 'x' in flags, 'l' in flags) if from_branch == branch: - parentid = self.get_parent_revision(self.current.rev.revnum, - branch) + parentid = self.meta.get_parent_revision(self.current.rev.revnum, + branch) if parentid != revlog.nullid: parentctx = self.repo.changectx(parentid) if util.aresamefiles(parentctx, ctx, [from_file]): @@ -834,7 +368,7 @@ class HgChangeReceiver(delta.Editor): def add_directory(self, path, parent_baton, copyfrom_path, copyfrom_revision, dir_pool=None): self.current.batons[path] = path - br_path, branch = self._path_and_branch_for_path(path) + br_path, branch = self.meta._path_and_branch_for_path(path) if br_path is not None: if not copyfrom_path and not br_path: self.current.emptybranches[branch] = True @@ -843,23 +377,23 @@ class HgChangeReceiver(delta.Editor): if br_path is None or not copyfrom_path: return path if copyfrom_path: - tag = self._is_path_tag(copyfrom_path) - if tag not in self.tags: + tag = self.meta._is_path_tag(copyfrom_path) + if tag not in self.meta.tags: tag = None - if not self._is_path_valid(copyfrom_path) and not tag: + if not self.meta._is_path_valid(copyfrom_path) and not tag: self.current.missing.add('%s/' % path) return path if tag: - source_branch, source_rev = self.tags[tag] + source_branch, source_rev = self.meta.tags[tag] cp_f = '' else: source_rev = copyfrom_revision - cp_f, source_branch = self._path_and_branch_for_path(copyfrom_path) + cp_f, source_branch = self.meta._path_and_branch_for_path(copyfrom_path) if cp_f == '' and br_path == '': assert br_path is not None - self.branches[branch] = source_branch, source_rev, self.current.rev.revnum - new_hash = self.get_parent_revision(source_rev + 1, - source_branch) + tmp = source_branch, source_rev, self.current.rev.revnum + self.meta.branches[branch] = tmp + new_hash = self.meta.get_parent_revision(source_rev + 1, source_branch) if new_hash == node.nullid: self.current.missing.add('%s/' % path) return path @@ -883,7 +417,7 @@ class HgChangeReceiver(delta.Editor): if copies: # Preserve the directory copy records if no file was changed between # the source and destination revisions, or discard it completely. - parentid = self.get_parent_revision(self.current.rev.revnum, branch) + parentid = self.meta.get_parent_revision(self.current.rev.revnum, branch) if parentid != revlog.nullid: parentctx = self.repo.changectx(parentid) if util.aresamefiles(parentctx, cp_f_ctx, copies.values()): @@ -908,7 +442,7 @@ class HgChangeReceiver(delta.Editor): @ieditor def open_directory(self, path, parent_baton, base_revision, dir_pool=None): self.current.batons[path] = path - p_, branch = self._path_and_branch_for_path(path) + p_, branch = self.meta._path_and_branch_for_path(path) if p_ == '': self.current.emptybranches[branch] = False return path @@ -925,7 +459,7 @@ class HgChangeReceiver(delta.Editor): # 2) Missing a base text (bail quick since we have to fetch a full plaintext) # 3) Has a base text in self.current.files, apply deltas base = '' - if not self._is_path_valid(self.current.file): + if not self.meta._is_path_valid(self.current.file): return lambda x: None assert self.current.file not in self.current.deleted, ( 'Cannot apply_textdelta to a deleted file: %s' % self.current.file) @@ -944,7 +478,7 @@ class HgChangeReceiver(delta.Editor): 'cannot call handler!') def txdelt_window(window): try: - if not self._is_path_valid(self.current.file): + if not self.meta._is_path_valid(self.current.file): return handler(window, baton) # window being None means commit this file