[PATCH 2 of 2 STABLE] amend: wrap all commit operation into a single transaction
Pierre-Yves David
pierre-yves.david at ens-lyon.org
Mon Jul 30 18:16:25 CDT 2012
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at ens-lyon.org>
# Date 1343689377 -7200
# Branch stable
# Node ID 1edb3dd232b9976a21bd3583dc3dfb29f833a6d3
# Parent 88f903c158c68499851eb7fd70859065c9a28170
amend: wrap all commit operation into a single transaction
This allows proper recovery of interrupted amend process.
No changes are made the the logic beside:
- indent operations into a single try-except clause,
- some comment and code wrapping to 80 chars,
- strip logic should not be contained in the transaction and are extracted from
the main code.
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -1572,125 +1572,133 @@
try:
lock = repo.lock()
try:
- # First, do a regular commit to record all changes in the working
- # directory (if there are any)
- ui.callhooks = False
+ tr = repo.transaction('amend')
try:
- node = commit(ui, repo, commitfunc, pats, opts)
- finally:
- ui.callhooks = True
- ctx = repo[node]
+ # First, do a regular commit to record all changes in the
+ # working directory (if there are any)
+ ui.callhooks = False
+ try:
+ node = commit(ui, repo, commitfunc, pats, opts)
+ finally:
+ ui.callhooks = True
+ ctx = repo[node]
- # Participating changesets:
- #
- # node/ctx o - new (intermediate) commit that contains changes from
- # | working dir to go into amending commit
- # | (or a workingctx if there were no changes)
- # |
- # old o - changeset to amend
- # |
- # base o - parent of amending changeset
+ # Participating changesets:
+ #
+ # node/ctx o - new (intermediate) commit that contains changes
+ # | from working dir to go into amending commit
+ # | (or a workingctx if there were no changes)
+ # |
+ # old o - changeset to amend
+ # |
+ # base o - parent of amending changeset
- # Update extra dict from amended commit
- # (e.g. to preserve graft source)
- extra.update(old.extra())
+ # Update extra dict from amended commit
+ # (e.g. to preserve graft source)
+ extra.update(old.extra())
- # Also update it from the intermediate commit or from the wctx
- extra.update(ctx.extra())
+ # Also update it from the intermediate commit or from the wctx
+ extra.update(ctx.extra())
- files = set(old.files())
+ files = set(old.files())
- # Second, we use either the commit we just did, or if there were no
- # changes the parent of the working directory as the version of the
- # files in the final amend commit
- if node:
- ui.note(_('copying changeset %s to %s\n') % (ctx, base))
+ # Second, we use either the commit we just did, or if there
+ # were no changes the parent of the working directory as the
+ # version of the files in the final amend commit
+ if node:
+ ui.note(_('copying changeset %s to %s\n') % (ctx, base))
- user = ctx.user()
- date = ctx.date()
- message = ctx.description()
- # Recompute copies (avoid recording a -> b -> a)
- copied = copies.pathcopies(base, ctx)
+ user = ctx.user()
+ date = ctx.date()
+ message = ctx.description()
+ # Recompute copies (avoid recording a -> b -> a)
+ copied = copies.pathcopies(base, ctx)
- # Prune files which were reverted by the updates: if old
- # introduced file X and our intermediate commit, node, renamed
- # that file, then those two files are the same and we can
- # discard X from our list of files. Likewise if X was deleted,
- # it's no longer relevant
- files.update(ctx.files())
+ # Prune files which were reverted by the updates: if old
+ # introduced file X and our intermediate commit, node,
+ # renamed that file, then those two files are the same and
+ # we can discard X from our list of files. Likewise if X
+ # was deleted, it's no longer relevant
+ files.update(ctx.files())
- def samefile(f):
- if f in ctx.manifest():
- a = ctx.filectx(f)
- if f in base.manifest():
- b = base.filectx(f)
- return (not a.cmp(b)
- and a.flags() == b.flags())
+ def samefile(f):
+ if f in ctx.manifest():
+ a = ctx.filectx(f)
+ if f in base.manifest():
+ b = base.filectx(f)
+ return (not a.cmp(b)
+ and a.flags() == b.flags())
+ else:
+ return False
else:
- return False
- else:
- return f not in base.manifest()
- files = [f for f in files if not samefile(f)]
+ return f not in base.manifest()
+ files = [f for f in files if not samefile(f)]
- def filectxfn(repo, ctx_, path):
- try:
- fctx = ctx[path]
- flags = fctx.flags()
- mctx = context.memfilectx(fctx.path(), fctx.data(),
- islink='l' in flags,
- isexec='x' in flags,
- copied=copied.get(path))
- return mctx
- except KeyError:
- raise IOError
- else:
- ui.note(_('copying changeset %s to %s\n') % (old, base))
+ def filectxfn(repo, ctx_, path):
+ try:
+ fctx = ctx[path]
+ flags = fctx.flags()
+ mctx = context.memfilectx(fctx.path(), fctx.data(),
+ islink='l' in flags,
+ isexec='x' in flags,
+ copied=copied.get(path))
+ return mctx
+ except KeyError:
+ raise IOError
+ else:
+ ui.note(_('copying changeset %s to %s\n') % (old, base))
- # Use version of files as in the old cset
- def filectxfn(repo, ctx_, path):
- try:
- return old.filectx(path)
- except KeyError:
- raise IOError
+ # Use version of files as in the old cset
+ def filectxfn(repo, ctx_, path):
+ try:
+ return old.filectx(path)
+ except KeyError:
+ raise IOError
- # See if we got a message from -m or -l, if not, open the
- # editor with the message of the changeset to amend
- user = opts.get('user') or old.user()
- date = opts.get('date') or old.date()
- message = logmessage(ui, opts)
- if not message:
- cctx = context.workingctx(repo, old.description(), user,
- date, extra,
- repo.status(base.node(),
- old.node()))
- message = commitforceeditor(repo, cctx, [])
+ # See if we got a message from -m or -l, if not, open the
+ # editor with the message of the changeset to amend
+ user = opts.get('user') or old.user()
+ date = opts.get('date') or old.date()
+ message = logmessage(ui, opts)
+ if not message:
+ cctx = context.workingctx(repo, old.description(),
+ user, date, extra,
+ repo.status(base.node(),
+ old.node()))
+ message = commitforceeditor(repo, cctx, [])
- new = context.memctx(repo,
- parents=[base.node(), nullid],
- text=message,
- files=files,
- filectxfn=filectxfn,
- user=user,
- date=date,
- extra=extra)
- newid = repo.commitctx(new)
- if newid != old.node():
- # Reroute the working copy parent to the new changeset
- repo.setparents(newid, nullid)
+ new = context.memctx(repo,
+ parents=[base.node(), nullid],
+ text=message,
+ files=files,
+ filectxfn=filectxfn,
+ user=user,
+ date=date,
+ extra=extra)
+ newid = repo.commitctx(new)
+ if newid != old.node():
+ # Reroute the working copy parent to the new changeset
+ repo.setparents(newid, nullid)
- # Move bookmarks from old parent to amend commit
- bms = repo.nodebookmarks(old.node())
- if bms:
- for bm in bms:
- repo._bookmarks[bm] = newid
- bookmarks.write(repo)
+ # Move bookmarks from old parent to amend commit
+ bms = repo.nodebookmarks(old.node())
+ if bms:
+ for bm in bms:
+ repo._bookmarks[bm] = newid
+ bookmarks.write(repo)
+ #commit the whole amend process
+ tr.close()
# Strip the intermediate commit (if there was one) and the
# amended commit
- if node:
- ui.note(_('stripping intermediate changeset %s\n') % ctx)
- ui.note(_('stripping amended changeset %s\n') % old)
- repair.strip(ui, repo, old.node(), topic='amend-backup')
+ if newid != old.node():
+ if node:
+ ui.note(_('stripping intermediate changeset %s\n')
+ % ctx)
+ ui.note(_('stripping amended changeset %s\n') % old)
+ repair.strip(ui, repo, old.node(), topic='amend-backup')
+ finally:
+ tr.release()
finally:
lock.release()
finally:
More information about the Mercurial-devel
mailing list