--- a/hgext/evolution.py Tue Jan 24 09:53:34 2012 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,386 +0,0 @@
-# states.py - introduce the state concept for mercurial changeset
-#
-# Copyright 2011 Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
-# Logilab SA <contact@logilab.fr>
-# Pierre-Yves David <pierre-yves.david@ens-lyon.org>
-#
-# This software may be used and distributed according to the terms of the
-# GNU General Public License version 2 or any later version.
-
-'''A set of command to make changeset evolve.'''
-
-from mercurial import cmdutil
-from mercurial import scmutil
-from mercurial import node
-from mercurial import error
-from mercurial import extensions
-from mercurial import commands
-from mercurial import bookmarks
-from mercurial import phases
-from mercurial import context
-from mercurial import commands
-from mercurial import util
-from mercurial.i18n import _
-from mercurial.commands import walkopts, commitopts, commitopts2, logopt
-from mercurial import hg
-
-### util function
-#############################
-def noderange(repo, revsets):
- """The same as revrange but return node"""
- return map(repo.changelog.node,
- scmutil.revrange(repo, revsets))
-
-### extension check
-#############################
-
-def extsetup(ui):
- try:
- obsolete = extensions.find('obsolete')
- except KeyError:
- raise error.Abort(_('evolution extension require obsolete extension.'))
- try:
- rebase = extensions.find('rebase')
- except KeyError:
- raise error.Abort(_('evolution extension require rebase extension.'))
-
-### changeset rewriting logic
-#############################
-
-def rewrite(repo, old, updates, head, newbases, commitopts):
- if len(old.parents()) > 1: #XXX remove this unecessary limitation.
- raise error.Abort(_('cannot amend merge changesets'))
- base = old.p1()
- bm = bookmarks.readcurrent(repo)
-
- wlock = repo.wlock()
- try:
-
- # commit a new version of the old changeset, including the update
- # collect all files which might be affected
- files = set(old.files())
- for u in updates:
- files.update(u.files())
- # prune files which were reverted by the updates
- def samefile(f):
- if f in head.manifest():
- a = head.filectx(f)
- if f in base.manifest():
- b = base.filectx(f)
- return (a.data() == b.data()
- and a.flags() == b.flags()
- and a.renamed() == b.renamed())
- else:
- return False
- else:
- return f not in base.manifest()
- files = [f for f in files if not samefile(f)]
- # commit version of these files as defined by head
- headmf = head.manifest()
- def filectxfn(repo, ctx, path):
- if path in headmf:
- return head.filectx(path)
- raise IOError()
- if commitopts.get('message') and commitopts.get('logfile'):
- raise util.Abort(_('options --message and --logfile are mutually'
- ' exclusive'))
- if commitopts.get('logfile'):
- message= open(commitopts['logfile']).read()
- elif commitopts.get('message'):
- message = commitopts['message']
- else:
- message = old.description()
-
-
-
- new = context.memctx(repo,
- parents=newbases,
- text=message,
- files=files,
- filectxfn=filectxfn,
- user=commitopts.get('user') or None,
- date=commitopts.get('date') or None,
- extra=commitopts.get('extra') or None)
-
- if commitopts.get('edit'):
- new._text = cmdutil.commitforceeditor(repo, new, [])
- newid = repo.commitctx(new)
- new = repo[newid]
-
- # update the bookmark
- if bm:
- repo._bookmarks[bm] = newid
- bookmarks.write(repo)
-
- # hide obsolete csets
- repo.changelog.hiddeninit = False
-
- # add evolution metadata
- repo.addobsolete(new.node(), old.node())
- for u in updates:
- repo.addobsolete(u.node(), old.node())
- repo.addobsolete(new.node(), u.node())
-
- finally:
- wlock.release()
-
- return newid
-
-def relocate(repo, rev, dest):
- """rewrite <rev> on dest"""
- try:
- rebase = extensions.find('rebase')
- # dummy state to trick rebase node
- assert repo[rev].p2().rev() == node.nullrev, 'no support yet'
- cmdutil.duplicatecopies(repo, rev, repo[dest].node(),
- repo[rev].p2().node())
- rebase.rebasenode(repo, rev, dest, {node.nullrev: node.nullrev})
- nodenew = rebase.concludenode(repo, rev, dest, node.nullid)
- nodesrc = repo.changelog.node(rev)
- repo.addobsolete(nodenew, nodesrc)
- phases.retractboundary(repo, repo[nodesrc].phase(), [nodenew])
- oldbookmarks = repo.nodebookmarks(nodesrc)
- for book in oldbookmarks:
- repo._bookmarks[book] = nodenew
- if oldbookmarks:
- bookmarks.write(repo)
- except util.Abort:
- # Invalidate the previous setparents
- repo.dirstate.invalidate()
- raise
-
-
-
-### new command
-#############################
-cmdtable = {}
-command = cmdutil.command(cmdtable)
-
-@command('^evolve',
- [],
- '')
-def evolve(ui, repo):
- """suggest the next evolution step"""
- obsolete = extensions.find('obsolete')
- next = min(obsolete.unstables(repo))
- obs = repo[next].parents()[0]
- if not obs.obsolete():
- obs = next.parents()[1]
- assert obs.obsolete()
- newer = obsolete.newerversion(repo, obs.node())
- target = newer[-1]
- repo.ui.status('hg relocate --rev %s %s\n' % (repo[next], repo[target]))
-
-shorttemplate = '[{rev}] {desc|firstline}\n'
-
-@command('^gdown',
- [],
- 'update to working directory parent an display summary lines')
-def cmdgdown(ui, repo):
- wkctx = repo[None]
- wparents = wkctx.parents()
- if len(wparents) != 1:
- raise util.Abort('merge in progress')
-
- parents = wparents[0].parents()
- displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
- if len(parents) == 1:
- p = parents[0]
- hg.update(repo, p.rev())
- displayer.show(p)
- return 0
- else:
- for p in parents:
- displayer.show(p)
- ui.warn(_('multiple parents, explicitly update to one\n'))
- return 1
-
-@command('^gup',
- [],
- 'update to working directory children an display summary lines')
-def cmdup(ui, repo):
- wkctx = repo[None]
- wparents = wkctx.parents()
- if len(wparents) != 1:
- raise util.Abort('merge in progress')
-
- children = [ctx for ctx in wparents[0].children() if not ctx.obsolete()]
- displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
- if not children:
- ui.warn(_('No non-obsolete children\n'))
- return 1
- if len(children) == 1:
- c = children[0]
- hg.update(repo, c.rev())
- displayer.show(c)
- return 0
- else:
- for c in children:
- displayer.show(c)
- ui.warn(_('Multiple non-obsolete children, explicitly update to one\n'))
- return 1
-
-
-@command('^kill',
- [
- ('n', 'new', [], _("New changeset that justify this one to be killed"))
- ],
- '<revs>')
-def kill(ui, repo, *revs, **opts):
- """mark a changeset as obsolete
-
- This update the parent directory to a not-killed parent if the current
- working directory parent are killed.
-
- XXX bookmark support
- XXX handle merge
- XXX check immutable first
- """
- wlock = repo.wlock()
- try:
- new = opts['new']
- targetnodes = set(noderange(repo, revs))
- if not new:
- new = [node.nullid]
- for n in targetnodes:
- if not repo[n].mutable():
- ui.warn(_("Can't kill immutable changeset %s") % repo[n])
- else:
- for ne in new:
- repo.addobsolete(ne, n)
- # update to an unkilled parent
- wdp = repo['.']
- newnode = wdp
- while newnode.obsolete():
- newnode = newnode.parents()[0]
- if newnode.node() != wdp.node():
- commands.update(ui, repo, newnode.rev())
- ui.status(_('working directory now at %s\n') % newnode)
-
- finally:
- wlock.release()
-
-@command('^amend',
- [('A', 'addremove', None,
- _('mark new/missing files as added/removed before committing')),
- ('n', 'note', '',
- _('use text as commit message for this update')),
- ('c', 'change', '',
- _('specifies the changeset to amend'), _('REV')),
- ('b', 'branch', '',
- _('specifies a branch for the new.'), _('REV')),
- ('e', 'edit', False,
- _('edit commit message.'), _('')),
- ] + walkopts + commitopts + commitopts2,
- _('[OPTION]... [FILE]...'))
-
-def amend(ui, repo, *pats, **opts):
- """combine a changeset with updates and replace it with a new one
-
- Commits a new changeset incorporating both the changes to the given files
- and all the changes from the current parent changeset into the repository.
-
- See :hg:`commit` for details about committing changes.
-
- If you don't specify -m, the parent's message will be reused.
-
- If you specify --change, amend additionally considers all changesets between
- the indicated changeset and the working copy parent as updates to be subsumed.
- This allows you to commit updates manually first. As a special shorthand you
- can say `--amend .` instead of '--amend p1(p1())', which subsumes your latest
- commit as an update of its parent.
-
- Behind the scenes, Mercurial first commits the update as a regular child
- of the current parent. Then it creates a new commit on the parent's parents
- with the updated contents. Then it changes the working copy parent to this
- new combined changeset. Finally, the old changeset and its update are hidden
- from :hg:`log` (unless you use --hidden with log).
-
- Returns 0 on success, 1 if nothing changed.
- """
-
- # determine updates to subsume
- change = opts.get('change')
- if change == '.':
- change = 'p1(p1())'
- old = scmutil.revsingle(repo, change)
- branch = opts.get('branch')
- if branch:
- opts.setdefault('extra', {})['branch'] = branch
- else:
- if old.branch() != 'default':
- opts.setdefault('extra', {})['branch'] = old.branch()
-
- lock = repo.lock()
- try:
- wlock = repo.wlock()
- try:
- if not old.phase():
- raise util.Abort(_("can not rewrite immutable changeset %s") % old)
-
- # commit current changes as update
- # code copied from commands.commit to avoid noisy messages
- ciopts = dict(opts)
- ciopts.pop('message', None)
- ciopts.pop('logfile', None)
- ciopts['message'] = opts.get('note') or ('amends %s' % old.hex())
- e = cmdutil.commiteditor
- def commitfunc(ui, repo, message, match, opts):
- return repo.commit(message, opts.get('user'), opts.get('date'), match,
- editor=e)
- cmdutil.commit(ui, repo, commitfunc, pats, ciopts)
-
- # find all changesets to be considered updates
- cl = repo.changelog
- head = repo['.']
- updatenodes = set(cl.nodesbetween(roots=[old.node()],
- heads=[head.node()])[0])
- updatenodes.remove(old.node())
- if not updatenodes and not (opts.get('message') or opts.get('logfile') or opts.get('edit')):
- raise error.Abort(_('no updates found'))
- updates = [repo[n] for n in updatenodes]
-
- # perform amend
- if opts.get('edit'):
- opts['force_editor'] = True
- newid = rewrite(repo, old, updates, head,
- [old.p1().node(), old.p2().node()], opts)
-
- # reroute the working copy parent to the new changeset
- phases.retractboundary(repo, old.phase(), [newid])
- repo.dirstate.setparents(newid, node.nullid)
- finally:
- wlock.release()
- finally:
- lock.release()
-
-def commitwrapper(orig, ui, repo, *arg, **kwargs):
- obsoleted = kwargs.get('obsolete', [])
- if obsoleted:
- obsoleted = repo.set('%lr', obsoleted)
- result = orig(ui, repo, *arg, **kwargs)
- if not result: # commit successed
- new = repo['-1']
- for old in obsoleted:
- repo.addobsolete(new.node(), old.node())
- return result
-
-def graftwrapper(orig, ui, repo, *revs, **kwargs):
- lock = repo.lock()
- try:
- if kwargs.get('old_obsolete'):
- obsoleted = kwargs.setdefault('obsolete', [])
- if kwargs['continue']:
- obsoleted.extend(repo.opener.read('graftstate').splitlines())
- else:
- obsoleted.extend(revs)
- return commitwrapper(orig, ui, repo,*revs, **kwargs)
- finally:
- lock.release()
-
-def extsetup(ui):
- entry = extensions.wrapcommand(commands.table, 'commit', commitwrapper)
- entry[1].append(('o', 'obsolete', [], _("this commit obsolet this revision")))
- entry = extensions.wrapcommand(commands.table, 'graft', graftwrapper)
- entry[1].append(('o', 'obsolete', [], _("this graft obsolet this revision")))
- entry[1].append(('O', 'old-obsolete', False, _("graft result obsolete graft source")))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/evolve.py Fri Feb 17 10:29:01 2012 +0100
@@ -0,0 +1,386 @@
+# states.py - introduce the state concept for mercurial changeset
+#
+# Copyright 2011 Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
+# Logilab SA <contact@logilab.fr>
+# Pierre-Yves David <pierre-yves.david@ens-lyon.org>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+'''A set of command to make changeset evolve.'''
+
+from mercurial import cmdutil
+from mercurial import scmutil
+from mercurial import node
+from mercurial import error
+from mercurial import extensions
+from mercurial import commands
+from mercurial import bookmarks
+from mercurial import phases
+from mercurial import context
+from mercurial import commands
+from mercurial import util
+from mercurial.i18n import _
+from mercurial.commands import walkopts, commitopts, commitopts2, logopt
+from mercurial import hg
+
+### util function
+#############################
+def noderange(repo, revsets):
+ """The same as revrange but return node"""
+ return map(repo.changelog.node,
+ scmutil.revrange(repo, revsets))
+
+### extension check
+#############################
+
+def extsetup(ui):
+ try:
+ obsolete = extensions.find('obsolete')
+ except KeyError:
+ raise error.Abort(_('evolution extension require obsolete extension.'))
+ try:
+ rebase = extensions.find('rebase')
+ except KeyError:
+ raise error.Abort(_('evolution extension require rebase extension.'))
+
+### changeset rewriting logic
+#############################
+
+def rewrite(repo, old, updates, head, newbases, commitopts):
+ if len(old.parents()) > 1: #XXX remove this unecessary limitation.
+ raise error.Abort(_('cannot amend merge changesets'))
+ base = old.p1()
+ bm = bookmarks.readcurrent(repo)
+
+ wlock = repo.wlock()
+ try:
+
+ # commit a new version of the old changeset, including the update
+ # collect all files which might be affected
+ files = set(old.files())
+ for u in updates:
+ files.update(u.files())
+ # prune files which were reverted by the updates
+ def samefile(f):
+ if f in head.manifest():
+ a = head.filectx(f)
+ if f in base.manifest():
+ b = base.filectx(f)
+ return (a.data() == b.data()
+ and a.flags() == b.flags()
+ and a.renamed() == b.renamed())
+ else:
+ return False
+ else:
+ return f not in base.manifest()
+ files = [f for f in files if not samefile(f)]
+ # commit version of these files as defined by head
+ headmf = head.manifest()
+ def filectxfn(repo, ctx, path):
+ if path in headmf:
+ return head.filectx(path)
+ raise IOError()
+ if commitopts.get('message') and commitopts.get('logfile'):
+ raise util.Abort(_('options --message and --logfile are mutually'
+ ' exclusive'))
+ if commitopts.get('logfile'):
+ message= open(commitopts['logfile']).read()
+ elif commitopts.get('message'):
+ message = commitopts['message']
+ else:
+ message = old.description()
+
+
+
+ new = context.memctx(repo,
+ parents=newbases,
+ text=message,
+ files=files,
+ filectxfn=filectxfn,
+ user=commitopts.get('user') or None,
+ date=commitopts.get('date') or None,
+ extra=commitopts.get('extra') or None)
+
+ if commitopts.get('edit'):
+ new._text = cmdutil.commitforceeditor(repo, new, [])
+ newid = repo.commitctx(new)
+ new = repo[newid]
+
+ # update the bookmark
+ if bm:
+ repo._bookmarks[bm] = newid
+ bookmarks.write(repo)
+
+ # hide obsolete csets
+ repo.changelog.hiddeninit = False
+
+ # add evolution metadata
+ repo.addobsolete(new.node(), old.node())
+ for u in updates:
+ repo.addobsolete(u.node(), old.node())
+ repo.addobsolete(new.node(), u.node())
+
+ finally:
+ wlock.release()
+
+ return newid
+
+def relocate(repo, rev, dest):
+ """rewrite <rev> on dest"""
+ try:
+ rebase = extensions.find('rebase')
+ # dummy state to trick rebase node
+ assert repo[rev].p2().rev() == node.nullrev, 'no support yet'
+ cmdutil.duplicatecopies(repo, rev, repo[dest].node(),
+ repo[rev].p2().node())
+ rebase.rebasenode(repo, rev, dest, {node.nullrev: node.nullrev})
+ nodenew = rebase.concludenode(repo, rev, dest, node.nullid)
+ nodesrc = repo.changelog.node(rev)
+ repo.addobsolete(nodenew, nodesrc)
+ phases.retractboundary(repo, repo[nodesrc].phase(), [nodenew])
+ oldbookmarks = repo.nodebookmarks(nodesrc)
+ for book in oldbookmarks:
+ repo._bookmarks[book] = nodenew
+ if oldbookmarks:
+ bookmarks.write(repo)
+ except util.Abort:
+ # Invalidate the previous setparents
+ repo.dirstate.invalidate()
+ raise
+
+
+
+### new command
+#############################
+cmdtable = {}
+command = cmdutil.command(cmdtable)
+
+@command('^evolve',
+ [],
+ '')
+def evolve(ui, repo):
+ """suggest the next evolution step"""
+ obsolete = extensions.find('obsolete')
+ next = min(obsolete.unstables(repo))
+ obs = repo[next].parents()[0]
+ if not obs.obsolete():
+ obs = next.parents()[1]
+ assert obs.obsolete()
+ newer = obsolete.newerversion(repo, obs.node())
+ target = newer[-1]
+ repo.ui.status('hg relocate --rev %s %s\n' % (repo[next], repo[target]))
+
+shorttemplate = '[{rev}] {desc|firstline}\n'
+
+@command('^gdown',
+ [],
+ 'update to working directory parent an display summary lines')
+def cmdgdown(ui, repo):
+ wkctx = repo[None]
+ wparents = wkctx.parents()
+ if len(wparents) != 1:
+ raise util.Abort('merge in progress')
+
+ parents = wparents[0].parents()
+ displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
+ if len(parents) == 1:
+ p = parents[0]
+ hg.update(repo, p.rev())
+ displayer.show(p)
+ return 0
+ else:
+ for p in parents:
+ displayer.show(p)
+ ui.warn(_('multiple parents, explicitly update to one\n'))
+ return 1
+
+@command('^gup',
+ [],
+ 'update to working directory children an display summary lines')
+def cmdup(ui, repo):
+ wkctx = repo[None]
+ wparents = wkctx.parents()
+ if len(wparents) != 1:
+ raise util.Abort('merge in progress')
+
+ children = [ctx for ctx in wparents[0].children() if not ctx.obsolete()]
+ displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
+ if not children:
+ ui.warn(_('No non-obsolete children\n'))
+ return 1
+ if len(children) == 1:
+ c = children[0]
+ hg.update(repo, c.rev())
+ displayer.show(c)
+ return 0
+ else:
+ for c in children:
+ displayer.show(c)
+ ui.warn(_('Multiple non-obsolete children, explicitly update to one\n'))
+ return 1
+
+
+@command('^kill',
+ [
+ ('n', 'new', [], _("New changeset that justify this one to be killed"))
+ ],
+ '<revs>')
+def kill(ui, repo, *revs, **opts):
+ """mark a changeset as obsolete
+
+ This update the parent directory to a not-killed parent if the current
+ working directory parent are killed.
+
+ XXX bookmark support
+ XXX handle merge
+ XXX check immutable first
+ """
+ wlock = repo.wlock()
+ try:
+ new = opts['new']
+ targetnodes = set(noderange(repo, revs))
+ if not new:
+ new = [node.nullid]
+ for n in targetnodes:
+ if not repo[n].mutable():
+ ui.warn(_("Can't kill immutable changeset %s") % repo[n])
+ else:
+ for ne in new:
+ repo.addobsolete(ne, n)
+ # update to an unkilled parent
+ wdp = repo['.']
+ newnode = wdp
+ while newnode.obsolete():
+ newnode = newnode.parents()[0]
+ if newnode.node() != wdp.node():
+ commands.update(ui, repo, newnode.rev())
+ ui.status(_('working directory now at %s\n') % newnode)
+
+ finally:
+ wlock.release()
+
+@command('^amend',
+ [('A', 'addremove', None,
+ _('mark new/missing files as added/removed before committing')),
+ ('n', 'note', '',
+ _('use text as commit message for this update')),
+ ('c', 'change', '',
+ _('specifies the changeset to amend'), _('REV')),
+ ('b', 'branch', '',
+ _('specifies a branch for the new.'), _('REV')),
+ ('e', 'edit', False,
+ _('edit commit message.'), _('')),
+ ] + walkopts + commitopts + commitopts2,
+ _('[OPTION]... [FILE]...'))
+
+def amend(ui, repo, *pats, **opts):
+ """combine a changeset with updates and replace it with a new one
+
+ Commits a new changeset incorporating both the changes to the given files
+ and all the changes from the current parent changeset into the repository.
+
+ See :hg:`commit` for details about committing changes.
+
+ If you don't specify -m, the parent's message will be reused.
+
+ If you specify --change, amend additionally considers all changesets between
+ the indicated changeset and the working copy parent as updates to be subsumed.
+ This allows you to commit updates manually first. As a special shorthand you
+ can say `--amend .` instead of '--amend p1(p1())', which subsumes your latest
+ commit as an update of its parent.
+
+ Behind the scenes, Mercurial first commits the update as a regular child
+ of the current parent. Then it creates a new commit on the parent's parents
+ with the updated contents. Then it changes the working copy parent to this
+ new combined changeset. Finally, the old changeset and its update are hidden
+ from :hg:`log` (unless you use --hidden with log).
+
+ Returns 0 on success, 1 if nothing changed.
+ """
+
+ # determine updates to subsume
+ change = opts.get('change')
+ if change == '.':
+ change = 'p1(p1())'
+ old = scmutil.revsingle(repo, change)
+ branch = opts.get('branch')
+ if branch:
+ opts.setdefault('extra', {})['branch'] = branch
+ else:
+ if old.branch() != 'default':
+ opts.setdefault('extra', {})['branch'] = old.branch()
+
+ lock = repo.lock()
+ try:
+ wlock = repo.wlock()
+ try:
+ if not old.phase():
+ raise util.Abort(_("can not rewrite immutable changeset %s") % old)
+
+ # commit current changes as update
+ # code copied from commands.commit to avoid noisy messages
+ ciopts = dict(opts)
+ ciopts.pop('message', None)
+ ciopts.pop('logfile', None)
+ ciopts['message'] = opts.get('note') or ('amends %s' % old.hex())
+ e = cmdutil.commiteditor
+ def commitfunc(ui, repo, message, match, opts):
+ return repo.commit(message, opts.get('user'), opts.get('date'), match,
+ editor=e)
+ cmdutil.commit(ui, repo, commitfunc, pats, ciopts)
+
+ # find all changesets to be considered updates
+ cl = repo.changelog
+ head = repo['.']
+ updatenodes = set(cl.nodesbetween(roots=[old.node()],
+ heads=[head.node()])[0])
+ updatenodes.remove(old.node())
+ if not updatenodes and not (opts.get('message') or opts.get('logfile') or opts.get('edit')):
+ raise error.Abort(_('no updates found'))
+ updates = [repo[n] for n in updatenodes]
+
+ # perform amend
+ if opts.get('edit'):
+ opts['force_editor'] = True
+ newid = rewrite(repo, old, updates, head,
+ [old.p1().node(), old.p2().node()], opts)
+
+ # reroute the working copy parent to the new changeset
+ phases.retractboundary(repo, old.phase(), [newid])
+ repo.dirstate.setparents(newid, node.nullid)
+ finally:
+ wlock.release()
+ finally:
+ lock.release()
+
+def commitwrapper(orig, ui, repo, *arg, **kwargs):
+ obsoleted = kwargs.get('obsolete', [])
+ if obsoleted:
+ obsoleted = repo.set('%lr', obsoleted)
+ result = orig(ui, repo, *arg, **kwargs)
+ if not result: # commit successed
+ new = repo['-1']
+ for old in obsoleted:
+ repo.addobsolete(new.node(), old.node())
+ return result
+
+def graftwrapper(orig, ui, repo, *revs, **kwargs):
+ lock = repo.lock()
+ try:
+ if kwargs.get('old_obsolete'):
+ obsoleted = kwargs.setdefault('obsolete', [])
+ if kwargs['continue']:
+ obsoleted.extend(repo.opener.read('graftstate').splitlines())
+ else:
+ obsoleted.extend(revs)
+ return commitwrapper(orig, ui, repo,*revs, **kwargs)
+ finally:
+ lock.release()
+
+def extsetup(ui):
+ entry = extensions.wrapcommand(commands.table, 'commit', commitwrapper)
+ entry[1].append(('o', 'obsolete', [], _("this commit obsolet this revision")))
+ entry = extensions.wrapcommand(commands.table, 'graft', graftwrapper)
+ entry[1].append(('o', 'obsolete', [], _("this graft obsolet this revision")))
+ entry[1].append(('O', 'old-obsolete', False, _("graft result obsolete graft source")))