Mercurial > hgsubversion
view hgsubversion/replay.py @ 547:9e6499c415a9
tags: fix files edited during tag creation
This was broken because file edits were skipped if they were in tags, but
committags in svnmeta didn't check to see if any files were changed during
initial tag creation.
author | Augie Fackler <durin42@gmail.com> |
---|---|
date | Sat, 06 Feb 2010 10:36:21 -0600 |
parents | cf4fe45bf8fd |
children | d17cec76e769 |
line wrap: on
line source
import errno import traceback from mercurial import revlog from mercurial import node from mercurial import context from mercurial import util as hgutil import svnexternals import util class MissingPlainTextError(Exception): """Exception raised when the repo lacks a source file required for replaying a txdelta. """ class ReplayException(Exception): """Exception raised when you try and commit but the replay encountered an exception. """ def convert_rev(ui, meta, svn, r, tbdelta): editor = meta.editor editor.current.clear() editor.current.rev = r svn.get_replay(r.revnum, editor) current = editor.current current.findmissing(svn) # update externals # TODO fix and re-enable externals for single-directory clones if current.externals and not meta.layout == 'single': # accumulate externals records for all branches revnum = current.rev.revnum branches = {} for path, entry in current.externals.iteritems(): if not meta.is_path_valid(path): ui.warn('WARNING: Invalid path %s in externals\n' % path) continue p, b, bp = meta.split_branch_path(path) if bp not in branches: external = svnexternals.externalsfile() parent = meta.get_parent_revision(revnum, b) pctx = meta.repo[parent] if '.hgsvnexternals' in pctx: external.read(pctx['.hgsvnexternals'].data()) branches[bp] = external else: external = branches[bp] external[p] = entry # register externals file changes for bp, external in branches.iteritems(): if bp and bp[-1] != '/': bp += '/' path = (bp and bp + '.hgsvnexternals') or '.hgsvnexternals' if external: current.set(path, external.write(), False, False) else: current.delete(path) if current.exception is not None: #pragma: no cover traceback.print_exception(*current.exception) raise ReplayException() if current.missing: raise MissingPlainTextError() # paranoidly generate the list of files to commit files_to_commit = set(current.files.keys()) files_to_commit.update(current.symlinks.keys()) files_to_commit.update(current.execfiles.keys()) files_to_commit.update(current.deleted.keys()) # back to a list and sort so we get sane behavior files_to_commit = list(files_to_commit) files_to_commit.sort() branch_batches = {} rev = current.rev date = meta.fixdate(rev.date) # build up the branches that have files on them for f in files_to_commit: if not meta.is_path_valid(f): continue p, b = meta.split_branch_path(f)[:2] if b not in branch_batches: branch_batches[b] = [] branch_batches[b].append((p, f)) closebranches = {} for branch in tbdelta['branches'][1]: branchedits = meta.revmap.branchedits(branch, rev) if len(branchedits) < 1: # can't close a branch that never existed continue ha = branchedits[0][1] closebranches[branch] = ha # 1. handle normal commits closedrevs = closebranches.values() for branch, files in branch_batches.iteritems(): if branch in current.emptybranches and files: del current.emptybranches[branch] files = dict(files) parents = meta.get_parent_revision(rev.revnum, branch), revlog.nullid if parents[0] in closedrevs and branch in meta.closebranches: continue extra = meta.genextra(rev.revnum, branch) tag = None if branch is not None: # New regular tag without modifications, it will be committed by # svnmeta.committag(), we can skip the whole branch for now tag = meta.get_path_tag(meta.remotename(branch)) if (tag and tag not in meta.tags and branch not in meta.branches and branch not in meta.repo.branchtags() and not files): continue parentctx = meta.repo.changectx(parents[0]) if tag: if parentctx.node() == node.nullid: continue extra.update({'branch': parentctx.extra().get('branch', None), 'close': 1}) if '.hgsvnexternals' not in parentctx and '.hgsvnexternals' in files: # Do not register empty externals files if (files['.hgsvnexternals'] in current.files and not current.files[files['.hgsvnexternals']]): del files['.hgsvnexternals'] def filectxfn(repo, memctx, path): current_file = files[path] if current_file in current.deleted: raise IOError(errno.EBADF, 'Operation on deleted file attempted') copied = current.copies.get(current_file) flags = parentctx.flags(path) is_exec = current.execfiles.get(current_file, 'x' in flags) is_link = current.symlinks.get(current_file, 'l' in flags) if current_file in current.files: data = current.files[current_file] if is_link and data.startswith('link '): data = data[len('link '):] elif is_link: ui.warn('file marked as link, but contains data: ' '%s (%r)\n' % (current_file, flags)) else: data = parentctx.filectx(path).data() return context.memfilectx(path=path, data=data, islink=is_link, isexec=is_exec, copied=copied) if not meta.usebranchnames or extra.get('branch', None) == 'default': extra.pop('branch', None) current_ctx = context.memctx(meta.repo, parents, rev.message or '...', files.keys(), filectxfn, meta.authors[rev.author], date, extra) new_hash = meta.repo.commitctx(current_ctx) util.describe_commit(ui, new_hash, branch) if (rev.revnum, branch) not in meta.revmap and not tag: meta.revmap[rev.revnum, branch] = new_hash if tag: meta.movetag(tag, new_hash, parentctx.extra().get('branch', None), rev, date) meta.addedtags.pop(tag, None) # 2. handle branches that need to be committed without any files for branch in current.emptybranches: ha = meta.get_parent_revision(rev.revnum, branch) if ha == node.nullid: continue parent_ctx = meta.repo.changectx(ha) def del_all_files(*args): raise IOError # True here meant nuke all files, shouldn't happen with branch closing if current.emptybranches[branch]: #pragma: no cover raise hgutil.Abort('Empty commit to an open branch attempted. ' 'Please report this issue.') extra = meta.genextra(rev.revnum, branch) if not meta.usebranchnames: extra.pop('branch', None) current_ctx = context.memctx(meta.repo, (ha, node.nullid), rev.message or ' ', [], del_all_files, meta.authors[rev.author], date, extra) new_hash = meta.repo.commitctx(current_ctx) util.describe_commit(ui, new_hash, branch) if (rev.revnum, branch) not in meta.revmap: meta.revmap[rev.revnum, branch] = new_hash return closebranches