##// END OF EJS Templates
amend: wrap all commit operations in a single transaction...
Pierre-Yves David -
r17472:965fbe04 default
parent child Browse files
Show More
@@ -1580,123 +1580,132 b' def amend(ui, repo, commitfunc, old, ext'
1580 try:
1580 try:
1581 wlock = repo.wlock()
1581 wlock = repo.wlock()
1582 lock = repo.lock()
1582 lock = repo.lock()
1583 # First, do a regular commit to record all changes in the working
1583 tr = repo.transaction('amend')
1584 # directory (if there are any)
1585 ui.callhooks = False
1586 try:
1584 try:
1587 node = commit(ui, repo, commitfunc, pats, opts)
1585 # First, do a regular commit to record all changes in the working
1588 finally:
1586 # directory (if there are any)
1589 ui.callhooks = True
1587 ui.callhooks = False
1590 ctx = repo[node]
1588 try:
1589 node = commit(ui, repo, commitfunc, pats, opts)
1590 finally:
1591 ui.callhooks = True
1592 ctx = repo[node]
1591
1593
1592 # Participating changesets:
1594 # Participating changesets:
1593 #
1595 #
1594 # node/ctx o - new (intermediate) commit that contains changes from
1596 # node/ctx o - new (intermediate) commit that contains changes
1595 # | working dir to go into amending commit (or a workingctx
1597 # | from working dir to go into amending commit
1596 # | if there were no changes)
1598 # | (or a workingctx if there were no changes)
1597 # |
1599 # |
1598 # old o - changeset to amend
1600 # old o - changeset to amend
1599 # |
1601 # |
1600 # base o - parent of amending changeset
1602 # base o - parent of amending changeset
1601
1603
1602 # Update extra dict from amended commit (e.g. to preserve graft source)
1604 # Update extra dict from amended commit (e.g. to preserve graft
1603 extra.update(old.extra())
1605 # source)
1606 extra.update(old.extra())
1604
1607
1605 # Also update it from the intermediate commit or from the wctx
1608 # Also update it from the intermediate commit or from the wctx
1606 extra.update(ctx.extra())
1609 extra.update(ctx.extra())
1607
1610
1608 files = set(old.files())
1611 files = set(old.files())
1609
1612
1610 # Second, we use either the commit we just did, or if there were no
1613 # Second, we use either the commit we just did, or if there were no
1611 # changes the parent of the working directory as the version of the
1614 # changes the parent of the working directory as the version of the
1612 # files in the final amend commit
1615 # files in the final amend commit
1613 if node:
1616 if node:
1614 ui.note(_('copying changeset %s to %s\n') % (ctx, base))
1617 ui.note(_('copying changeset %s to %s\n') % (ctx, base))
1615
1618
1616 user = ctx.user()
1619 user = ctx.user()
1617 date = ctx.date()
1620 date = ctx.date()
1618 message = ctx.description()
1621 message = ctx.description()
1619 # Recompute copies (avoid recording a -> b -> a)
1622 # Recompute copies (avoid recording a -> b -> a)
1620 copied = copies.pathcopies(base, ctx)
1623 copied = copies.pathcopies(base, ctx)
1621
1624
1622 # Prune files which were reverted by the updates: if old introduced
1625 # Prune files which were reverted by the updates: if old
1623 # file X and our intermediate commit, node, renamed that file, then
1626 # introduced file X and our intermediate commit, node,
1624 # those two files are the same and we can discard X from our list
1627 # renamed that file, then those two files are the same and
1625 # of files. Likewise if X was deleted, it's no longer relevant
1628 # we can discard X from our list of files. Likewise if X
1626 files.update(ctx.files())
1629 # was deleted, it's no longer relevant
1630 files.update(ctx.files())
1627
1631
1628 def samefile(f):
1632 def samefile(f):
1629 if f in ctx.manifest():
1633 if f in ctx.manifest():
1630 a = ctx.filectx(f)
1634 a = ctx.filectx(f)
1631 if f in base.manifest():
1635 if f in base.manifest():
1632 b = base.filectx(f)
1636 b = base.filectx(f)
1633 return (not a.cmp(b)
1637 return (not a.cmp(b)
1634 and a.flags() == b.flags())
1638 and a.flags() == b.flags())
1639 else:
1640 return False
1635 else:
1641 else:
1636 return False
1642 return f not in base.manifest()
1637 else:
1643 files = [f for f in files if not samefile(f)]
1638 return f not in base.manifest()
1639 files = [f for f in files if not samefile(f)]
1640
1644
1641 def filectxfn(repo, ctx_, path):
1645 def filectxfn(repo, ctx_, path):
1642 try:
1646 try:
1643 fctx = ctx[path]
1647 fctx = ctx[path]
1644 flags = fctx.flags()
1648 flags = fctx.flags()
1645 mctx = context.memfilectx(fctx.path(), fctx.data(),
1649 mctx = context.memfilectx(fctx.path(), fctx.data(),
1646 islink='l' in flags,
1650 islink='l' in flags,
1647 isexec='x' in flags,
1651 isexec='x' in flags,
1648 copied=copied.get(path))
1652 copied=copied.get(path))
1649 return mctx
1653 return mctx
1650 except KeyError:
1654 except KeyError:
1651 raise IOError
1655 raise IOError
1652 else:
1656 else:
1653 ui.note(_('copying changeset %s to %s\n') % (old, base))
1657 ui.note(_('copying changeset %s to %s\n') % (old, base))
1654
1658
1655 # Use version of files as in the old cset
1659 # Use version of files as in the old cset
1656 def filectxfn(repo, ctx_, path):
1660 def filectxfn(repo, ctx_, path):
1657 try:
1661 try:
1658 return old.filectx(path)
1662 return old.filectx(path)
1659 except KeyError:
1663 except KeyError:
1660 raise IOError
1664 raise IOError
1661
1665
1662 # See if we got a message from -m or -l, if not, open the editor
1666 # See if we got a message from -m or -l, if not, open the editor
1663 # with the message of the changeset to amend
1667 # with the message of the changeset to amend
1664 user = opts.get('user') or old.user()
1668 user = opts.get('user') or old.user()
1665 date = opts.get('date') or old.date()
1669 date = opts.get('date') or old.date()
1666 message = logmessage(ui, opts)
1670 message = logmessage(ui, opts)
1667 if not message:
1671 if not message:
1668 cctx = context.workingctx(repo, old.description(), user, date,
1672 cctx = context.workingctx(repo, old.description(),
1669 extra,
1673 user, date, extra,
1670 repo.status(base.node(), old.node()))
1674 repo.status(base.node(),
1671 message = commitforceeditor(repo, cctx, [])
1675 old.node()))
1676 message = commitforceeditor(repo, cctx, [])
1672
1677
1673 new = context.memctx(repo,
1678 new = context.memctx(repo,
1674 parents=[base.node(), nullid],
1679 parents=[base.node(), nullid],
1675 text=message,
1680 text=message,
1676 files=files,
1681 files=files,
1677 filectxfn=filectxfn,
1682 filectxfn=filectxfn,
1678 user=user,
1683 user=user,
1679 date=date,
1684 date=date,
1680 extra=extra)
1685 extra=extra)
1681 ph = repo.ui.config('phases', 'new-commit', phases.draft)
1686 ph = repo.ui.config('phases', 'new-commit', phases.draft)
1682 try:
1687 try:
1683 repo.ui.setconfig('phases', 'new-commit', old.phase())
1688 repo.ui.setconfig('phases', 'new-commit', old.phase())
1684 newid = repo.commitctx(new)
1689 newid = repo.commitctx(new)
1690 finally:
1691 repo.ui.setconfig('phases', 'new-commit', ph)
1692 if newid != old.node():
1693 # Reroute the working copy parent to the new changeset
1694 repo.setparents(newid, nullid)
1695
1696 # Move bookmarks from old parent to amend commit
1697 bms = repo.nodebookmarks(old.node())
1698 if bms:
1699 for bm in bms:
1700 repo._bookmarks[bm] = newid
1701 bookmarks.write(repo)
1702 #commit the whole amend process
1703 tr.close()
1685 finally:
1704 finally:
1686 repo.ui.setconfig('phases', 'new-commit', ph)
1705 tr.release()
1706 # Strip the intermediate commit (if there was one) and the amended
1707 # commit
1687 if newid != old.node():
1708 if newid != old.node():
1688 # Reroute the working copy parent to the new changeset
1689 repo.setparents(newid, nullid)
1690
1691 # Move bookmarks from old parent to amend commit
1692 bms = repo.nodebookmarks(old.node())
1693 if bms:
1694 for bm in bms:
1695 repo._bookmarks[bm] = newid
1696 bookmarks.write(repo)
1697
1698 # Strip the intermediate commit (if there was one) and the amended
1699 # commit
1700 if node:
1709 if node:
1701 ui.note(_('stripping intermediate changeset %s\n') % ctx)
1710 ui.note(_('stripping intermediate changeset %s\n') % ctx)
1702 ui.note(_('stripping amended changeset %s\n') % old)
1711 ui.note(_('stripping amended changeset %s\n') % old)
General Comments 0
You need to be logged in to leave comments. Login now