hgext/evolve.py
changeset 1575 0c8548df67fe
parent 1568 52c276d2ddb2
parent 1574 dcfe3afe548b
child 1576 526253198860
equal deleted inserted replaced
1568:52c276d2ddb2 1575:0c8548df67fe
   146 #####################################################################
   146 #####################################################################
   147 
   147 
   148 class exthelper(object):
   148 class exthelper(object):
   149     """Helper for modular extension setup
   149     """Helper for modular extension setup
   150 
   150 
   151     A single helper should be instanciated for each extension. Helper
   151     A single helper should be instantiated for each extension. Helper
   152     methods are then used as decorator for various purpose.
   152     methods are then used as decorators for various purpose.
   153 
   153 
   154     All decorators return the original function and may be chained.
   154     All decorators return the original function and may be chained.
   155     """
   155     """
   156 
   156 
   157     def __init__(self):
   157     def __init__(self):
   794     try:
   794     try:
   795         histedit = extensions.find('histedit')
   795         histedit = extensions.find('histedit')
   796         if histedit:
   796         if histedit:
   797             extensions.wrapcommand(histedit.cmdtable, 'histedit', warnobserrors)
   797             extensions.wrapcommand(histedit.cmdtable, 'histedit', warnobserrors)
   798     except KeyError:
   798     except KeyError:
   799         pass # rebase not found
   799         pass # histedit not found
   800 
   800 
   801 #####################################################################
   801 #####################################################################
   802 ### Old Evolve extension content                                  ###
   802 ### Old Evolve extension content                                  ###
   803 #####################################################################
   803 #####################################################################
   804 
   804 
  1100     _deprecatealias('gup', 'next')
  1100     _deprecatealias('gup', 'next')
  1101     _deprecatealias('gdown', 'previous')
  1101     _deprecatealias('gdown', 'previous')
  1102 
  1102 
  1103 @command('debugrecordpruneparents', [], '')
  1103 @command('debugrecordpruneparents', [], '')
  1104 def cmddebugrecordpruneparents(ui, repo):
  1104 def cmddebugrecordpruneparents(ui, repo):
  1105     """add parents data to prune markers when possible
  1105     """add parent data to prune markers when possible
  1106 
  1106 
  1107     This commands search the repo for prune markers without parent information.
  1107     This command searches the repo for prune markers without parent information.
  1108     If the pruned node is locally known, a new markers with parent data is
  1108     If the pruned node is locally known, it creates a new marker with parent
  1109     created."""
  1109     data.
       
  1110     """
  1110     pgop = 'reading markers'
  1111     pgop = 'reading markers'
  1111 
  1112 
  1112     # lock from the beginning to prevent race
  1113     # lock from the beginning to prevent race
  1113     wlock = lock = tr = None
  1114     wlock = lock = tr = None
  1114     try:
  1115     try:
  1136     finally:
  1137     finally:
  1137         lockmod.release(tr, lock, wlock)
  1138         lockmod.release(tr, lock, wlock)
  1138 
  1139 
  1139 @command('debugobsstorestat', [], '')
  1140 @command('debugobsstorestat', [], '')
  1140 def cmddebugobsstorestat(ui, repo):
  1141 def cmddebugobsstorestat(ui, repo):
       
  1142     """print statistics about obsolescence markers in the repo"""
  1141     def _updateclustermap(nodes, mark, clustersmap):
  1143     def _updateclustermap(nodes, mark, clustersmap):
  1142         c = (set(nodes), set([mark]))
  1144         c = (set(nodes), set([mark]))
  1143         toproceed = set(nodes)
  1145         toproceed = set(nodes)
  1144         while toproceed:
  1146         while toproceed:
  1145             n = toproceed.pop()
  1147             n = toproceed.pop()
  1153                         continue
  1155                         continue
  1154                     clustersmap[on] = other
  1156                     clustersmap[on] = other
  1155                 c = other
  1157                 c = other
  1156             clustersmap[n] = c
  1158             clustersmap[n] = c
  1157 
  1159 
  1158     """print statistic about obsolescence markers in the repo"""
       
  1159     store = repo.obsstore
  1160     store = repo.obsstore
  1160     unfi = repo.unfiltered()
  1161     unfi = repo.unfiltered()
  1161     nm = unfi.changelog.nodemap
  1162     nm = unfi.changelog.nodemap
  1162     ui.write(_('markers total:              %9i\n') % len(store._all))
  1163     ui.write(_('markers total:              %9i\n') % len(store._all))
  1163     sucscount = [0, 0 , 0, 0]
  1164     sucscount = [0, 0 , 0, 0]
  1368         ui.progress(_('evolve'), None)
  1369         ui.progress(_('evolve'), None)
  1369     if repo['.'] != startnode:
  1370     if repo['.'] != startnode:
  1370         ui.status(_('working directory is now at %s\n') % repo['.'])
  1371         ui.status(_('working directory is now at %s\n') % repo['.'])
  1371 
  1372 
  1372 class MultipleSuccessorsError(RuntimeError):
  1373 class MultipleSuccessorsError(RuntimeError):
  1373     """Exception raised by _singlesuccessor when multiple sucessors sets exists
  1374     """Exception raised by _singlesuccessor when multiple successor sets exists
  1374 
  1375 
  1375     The object contains the list of successorssets in its 'successorssets'
  1376     The object contains the list of successorssets in its 'successorssets'
  1376     attribute to call to easily recover.
  1377     attribute to call to easily recover.
  1377     """
  1378     """
  1378 
  1379 
  1472 
  1473 
  1473 
  1474 
  1474 def _orderrevs(repo, revs):
  1475 def _orderrevs(repo, revs):
  1475     """Compute an ordering to solve instability for the given revs
  1476     """Compute an ordering to solve instability for the given revs
  1476 
  1477 
  1477     - Takes revs a list of instable revisions
  1478     revs is a list of unstable revisions.
  1478 
  1479 
  1479     - Returns the same revisions ordered to solve their instability from the
  1480     Returns the same revisions ordered to solve their instability from the
  1480     bottom to the top of the stack that the stabilization process will produce
  1481     bottom to the top of the stack that the stabilization process will produce
  1481     eventually.
  1482     eventually.
  1482 
  1483 
  1483     This ensure the minimal number of stabilization as we can stabilize each
  1484     This ensures the minimal number of stabilizations, as we can stabilize each
  1484     revision on its final, stabilized, destination.
  1485     revision on its final stabilized destination.
  1485     """
  1486     """
  1486     # Step 1: Build the dependency graph
  1487     # Step 1: Build the dependency graph
  1487     dependencies, rdependencies = builddependencies(repo, revs)
  1488     dependencies, rdependencies = builddependencies(repo, revs)
  1488     # Step 2: Build the ordering
  1489     # Step 2: Build the ordering
  1489     # Remove the revisions with no dependency(A) and add them to the ordering.
  1490     # Remove the revisions with no dependency(A) and add them to the ordering.
  1730                 result.add(unstable)
  1731                 result.add(unstable)
  1731     return sorted(result - target)
  1732     return sorted(result - target)
  1732 
  1733 
  1733 def _solveunstable(ui, repo, orig, dryrun=False, confirm=False,
  1734 def _solveunstable(ui, repo, orig, dryrun=False, confirm=False,
  1734                    progresscb=None):
  1735                    progresscb=None):
  1735     """Stabilize a unstable changeset"""
  1736     """Stabilize an unstable changeset"""
  1736     obs = orig.parents()[0]
  1737     obs = orig.parents()[0]
  1737     if not obs.obsolete() and len(orig.parents()) == 2:
  1738     if not obs.obsolete() and len(orig.parents()) == 2:
  1738         obs = orig.parents()[1] # second parent is obsolete ?
  1739         obs = orig.parents()[1] # second parent is obsolete ?
  1739 
  1740 
  1740     if not obs.obsolete():
  1741     if not obs.obsolete():
  2056           ('', 'merge', False, _('bring uncommitted change along')),
  2057           ('', 'merge', False, _('bring uncommitted change along')),
  2057           ('n', 'dry-run', False,
  2058           ('n', 'dry-run', False,
  2058              _('do not perform actions, just print what would be done'))],
  2059              _('do not perform actions, just print what would be done'))],
  2059          '[OPTION]...')
  2060          '[OPTION]...')
  2060 def cmdprevious(ui, repo, **opts):
  2061 def cmdprevious(ui, repo, **opts):
  2061     """update to parent and display summary lines"""
  2062     """update to parent revision
       
  2063 
       
  2064     Displays the summary line of the destination for clarity."""
  2062     wkctx = repo[None]
  2065     wkctx = repo[None]
  2063     wparents = wkctx.parents()
  2066     wparents = wkctx.parents()
  2064     dryrunopt = opts['dry_run']
  2067     dryrunopt = opts['dry_run']
  2065     if len(wparents) != 1:
  2068     if len(wparents) != 1:
  2066         raise error.Abort('merge in progress')
  2069         raise error.Abort('merge in progress')
  2112           ('', 'evolve', False, _('evolve the next changeset if necessary')),
  2115           ('', 'evolve', False, _('evolve the next changeset if necessary')),
  2113           ('n', 'dry-run', False,
  2116           ('n', 'dry-run', False,
  2114               _('do not perform actions, just print what would be done'))],
  2117               _('do not perform actions, just print what would be done'))],
  2115               '[OPTION]...')
  2118               '[OPTION]...')
  2116 def cmdnext(ui, repo, **opts):
  2119 def cmdnext(ui, repo, **opts):
  2117     """update to next child
  2120     """update to next child revision
  2118 
  2121 
  2119     You can use the --evolve flag to get unstable children evolved on demand.
  2122     Use the ``--evolve`` flag to evolve unstable children on demand.
  2120 
  2123 
  2121     The summary line of the destination is displayed for clarity"""
  2124     Displays the summary line of the destination for clarity.
       
  2125     """
  2122     wkctx = repo[None]
  2126     wkctx = repo[None]
  2123     wparents = wkctx.parents()
  2127     wparents = wkctx.parents()
  2124     dryrunopt = opts['dry_run']
  2128     dryrunopt = opts['dry_run']
  2125     if len(wparents) != 1:
  2129     if len(wparents) != 1:
  2126         raise error.Abort('merge in progress')
  2130         raise error.Abort('merge in progress')
  2263     _('[OPTION] [-r] REV...'))
  2267     _('[OPTION] [-r] REV...'))
  2264     # -U  --noupdate option to prevent wc update and or bookmarks update ?
  2268     # -U  --noupdate option to prevent wc update and or bookmarks update ?
  2265 def cmdprune(ui, repo, *revs, **opts):
  2269 def cmdprune(ui, repo, *revs, **opts):
  2266     """hide changesets by marking them obsolete
  2270     """hide changesets by marking them obsolete
  2267 
  2271 
  2268     Obsolete changesets becomes invisible to all commands.
  2272     Pruned changesets are obsolete with no successors. If they also have no
  2269 
  2273     descendants, they are hidden (invisible to all commands).
  2270     Unpruned descendants of pruned changesets becomes "unstable". Use the
  2274 
  2271     :hg:`evolve` to handle such situation.
  2275     Non-obsolete descendants of pruned changesets become "unstable". Use :hg:`evolve`
  2272 
  2276     to handle this situation.
  2273     When the working directory parent is pruned, the repository is updated to a
  2277 
  2274     non-obsolete parent.
  2278     When you prune the parent of your working copy, Mercurial updates the working
  2275 
  2279     copy to a non-obsolete parent.
  2276     You can use the ``--succ`` option to inform mercurial that a newer version
  2280 
  2277     of the pruned changeset exists.
  2281     You can use ``--succ`` to tell Mercurial that a newer version (successor) of the
  2278 
  2282     pruned changeset exists. Mercurial records successor revisions in obsolescence
  2279     You can use the ``--biject`` option to specify a 1-1 (bijection) between
  2283     markers.
  2280     revisions to prune and successor changesets. This option may be removed in
  2284 
  2281     a future release (with the functionality absorbed automatically).
  2285     You can use the ``--biject`` option to specify a 1-1 mapping (bijection) between
  2282 
  2286     revisions to pruned (precursor) and successor changesets. This option may be
  2283     If you specify multiple revisions in --succ, you are recording a "split"
  2287     removed in a future release (with the functionality provided automatically).
  2284     and have to acknowledge it by usng --split. The same logic apply when you
  2288 
  2285     prune multiple changesets with a single successors, this will record a
  2289     If you specify multiple revisions in ``--succ``, you are recording a "split" and
  2286     "fold" requires a --fold flag.
  2290     must acknowledge it by passing ``--split``. Similarly, when you prune multiple
       
  2291     changesets with a single successor, you must pass the ``--fold`` option.
  2287     """
  2292     """
  2288     revs = scmutil.revrange(repo, list(revs) + opts.get('rev'))
  2293     revs = scmutil.revrange(repo, list(revs) + opts.get('rev'))
  2289     succs = opts['new'] + opts['succ']
  2294     succs = opts['new'] + opts['succ']
  2290     bookmarks = set(opts.get('bookmark'))
  2295     bookmarks = set(opts.get('bookmark'))
  2291     metadata = _getmetadata(**opts)
  2296     metadata = _getmetadata(**opts)
  2686 @command('^split',
  2691 @command('^split',
  2687     [('r', 'rev', [], _("revision to fold")),
  2692     [('r', 'rev', [], _("revision to fold")),
  2688     ] + commitopts + commitopts2,
  2693     ] + commitopts + commitopts2,
  2689     _('hg split [OPTION]... [-r] REV'))
  2694     _('hg split [OPTION]... [-r] REV'))
  2690 def cmdsplit(ui, repo, *revs, **opts):
  2695 def cmdsplit(ui, repo, *revs, **opts):
  2691     """Split the current commit using interactive selection
  2696     """split a changeset into smaller changesets
  2692 
  2697 
  2693     By default, split the current revision by prompting for all its hunk to be
  2698     By default, split the current revision by prompting for all its hunks to be
  2694     redistributed into new changesets.
  2699     redistributed into new changesets.
  2695 
  2700 
  2696     Use --rev for splitting a given changeset instead.
  2701     Use --rev to split a given changeset instead.
  2697     """
  2702     """
  2698     tr = wlock = lock = None
  2703     tr = wlock = lock = None
  2699     newcommits = []
  2704     newcommits = []
  2700 
  2705 
  2701     revopt = opts.get('rev')
  2706     revopt = opts.get('rev')