hgext/histedit.py
changeset 22977 29ae3b190ec5
parent 22976 886711722db6
child 22978 d4e764521249
equal deleted inserted replaced
22976:886711722db6 22977:29ae3b190ec5
   558             if len(revs) != 1:
   558             if len(revs) != 1:
   559                 raise util.Abort(
   559                 raise util.Abort(
   560                     _('histedit requires exactly one ancestor revision'))
   560                     _('histedit requires exactly one ancestor revision'))
   561 
   561 
   562 
   562 
       
   563     replacements = []
       
   564     keep = opts.get('keep', False)
       
   565 
       
   566     # rebuild state
   563     if goal == 'continue':
   567     if goal == 'continue':
   564         (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
   568         state = readstate(repo)
   565         parentctx = repo[parentctxnode]
   569         parentctx = repo[state.parentctxnode]
   566         parentctx, repl = bootstrapcontinue(ui, repo, parentctx, rules, opts)
   570         parentctx, repl = bootstrapcontinue(ui, repo, parentctx, state.rules,
   567         replacements.extend(repl)
   571                 opts)
       
   572         state.replacements.extend(repl)
       
   573         state.parentctxnode = parentctx.node()
   568     elif goal == 'abort':
   574     elif goal == 'abort':
   569         (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
   575         state = readstate(repo)
   570         mapping, tmpnodes, leafs, _ntm = processreplacement(repo, replacements)
   576         mapping, tmpnodes, leafs, _ntm = processreplacement(repo,
   571         ui.debug('restore wc to old parent %s\n' % node.short(topmost))
   577                 state.replacements)
       
   578         ui.debug('restore wc to old parent %s\n' % node.short(state.topmost))
   572         # check whether we should update away
   579         # check whether we should update away
   573         parentnodes = [c.node() for c in repo[None].parents()]
   580         parentnodes = [c.node() for c in repo[None].parents()]
   574         for n in leafs | set([parentctxnode]):
   581         for n in leafs | set([state.parentctxnode]):
   575             if n in parentnodes:
   582             if n in parentnodes:
   576                 hg.clean(repo, topmost)
   583                 hg.clean(repo, state.topmost)
   577                 break
   584                 break
   578         else:
   585         else:
   579             pass
   586             pass
   580         cleanupnode(ui, repo, 'created', tmpnodes)
   587         cleanupnode(ui, repo, 'created', tmpnodes)
   581         cleanupnode(ui, repo, 'temp', leafs)
   588         cleanupnode(ui, repo, 'temp', leafs)
   597             if len(rr) != 1:
   604             if len(rr) != 1:
   598                 raise util.Abort(_('The specified revisions must have '
   605                 raise util.Abort(_('The specified revisions must have '
   599                     'exactly one common root'))
   606                     'exactly one common root'))
   600             root = rr[0].node()
   607             root = rr[0].node()
   601 
   608 
   602         keep = opts.get('keep', False)
       
   603         revs = between(repo, root, topmost, keep)
   609         revs = between(repo, root, topmost, keep)
   604         if not revs:
   610         if not revs:
   605             raise util.Abort(_('%s is not an ancestor of working directory') %
   611             raise util.Abort(_('%s is not an ancestor of working directory') %
   606                              node.short(root))
   612                              node.short(root))
   607 
   613 
   627         rules = [l for l in (r.strip() for r in rules.splitlines())
   633         rules = [l for l in (r.strip() for r in rules.splitlines())
   628                  if l and not l.startswith('#')]
   634                  if l and not l.startswith('#')]
   629         rules = verifyrules(rules, repo, ctxs)
   635         rules = verifyrules(rules, repo, ctxs)
   630 
   636 
   631         parentctx = repo[root].parents()[0]
   637         parentctx = repo[root].parents()[0]
   632         replacements = []
   638 
   633 
   639         state = histeditstate(repo, parentctx.node(), rules, keep,
   634 
   640                     topmost, replacements)
   635     while rules:
   641 
   636         writestate(repo, parentctx.node(), rules, keep, topmost, replacements)
   642     while state.rules:
   637         action, ha = rules.pop(0)
   643         state.write()
       
   644         action, ha = state.rules.pop(0)
   638         ui.debug('histedit: processing %s %s\n' % (action, ha))
   645         ui.debug('histedit: processing %s %s\n' % (action, ha))
   639         actfunc = actiontable[action]
   646         actfunc = actiontable[action]
   640         parentctx, replacement_ = actfunc(ui, repo, parentctx, ha, opts)
   647         parentctx = repo[state.parentctxnode]
   641         replacements.extend(replacement_)
   648         parentctx, replacement_ = actfunc(ui, repo, parentctx,
   642 
   649                 ha, opts)
   643     hg.update(repo, parentctx.node())
   650         state.parentctxnode = parentctx.node()
   644 
   651         state.replacements.extend(replacement_)
   645     mapping, tmpnodes, created, ntm = processreplacement(repo, replacements)
   652 
       
   653     hg.update(repo, state.parentctxnode)
       
   654 
       
   655     mapping, tmpnodes, created, ntm = processreplacement(repo,
       
   656             state.replacements)
   646     if mapping:
   657     if mapping:
   647         for prec, succs in mapping.iteritems():
   658         for prec, succs in mapping.iteritems():
   648             if not succs:
   659             if not succs:
   649                 ui.debug('histedit: %s is dropped\n' % node.short(prec))
   660                 ui.debug('histedit: %s is dropped\n' % node.short(prec))
   650             else:
   661             else:
   655                     for n in succs[1:]:
   666                     for n in succs[1:]:
   656                         ui.debug(m % node.short(n))
   667                         ui.debug(m % node.short(n))
   657 
   668 
   658     if not keep:
   669     if not keep:
   659         if mapping:
   670         if mapping:
   660             movebookmarks(ui, repo, mapping, topmost, ntm)
   671             movebookmarks(ui, repo, mapping, state.topmost, ntm)
   661             # TODO update mq state
   672             # TODO update mq state
   662         if obsolete.isenabled(repo, obsolete.createmarkersopt):
   673         if obsolete.isenabled(repo, obsolete.createmarkersopt):
   663             markers = []
   674             markers = []
   664             # sort by revision number because it sound "right"
   675             # sort by revision number because it sound "right"
   665             for prec in sorted(mapping, key=repo.changelog.rev):
   676             for prec in sorted(mapping, key=repo.changelog.rev):
   765         root = ctxs[0] # list is already sorted by repo.set
   776         root = ctxs[0] # list is already sorted by repo.set
   766         if not root.mutable():
   777         if not root.mutable():
   767             raise util.Abort(_('cannot edit immutable changeset: %s') % root)
   778             raise util.Abort(_('cannot edit immutable changeset: %s') % root)
   768     return [c.node() for c in ctxs]
   779     return [c.node() for c in ctxs]
   769 
   780 
   770 
       
   771 def writestate(repo, parentnode, rules, keep, topmost, replacements):
       
   772     fp = open(os.path.join(repo.path, 'histedit-state'), 'w')
       
   773     pickle.dump((parentnode, rules, keep, topmost, replacements), fp)
       
   774     fp.close()
       
   775 
       
   776 def readstate(repo):
   781 def readstate(repo):
   777     """Returns a tuple of (parentnode, rules, keep, topmost, replacements).
   782     """Reads a state from file and returns a histeditstate object
   778     """
   783     """
   779     try:
   784     try:
   780         fp = open(os.path.join(repo.path, 'histedit-state'))
   785         fp = repo.vfs('histedit-state', 'r')
   781     except IOError, err:
   786     except IOError, err:
   782         if err.errno != errno.ENOENT:
   787         if err.errno != errno.ENOENT:
   783             raise
   788             raise
   784         raise util.Abort(_('no histedit in progress'))
   789         raise util.Abort(_('no histedit in progress'))
   785     return pickle.load(fp)
   790 
   786 
   791     (parentctxnode, rules, keep, topmost, replacements) = pickle.load(fp)
       
   792 
       
   793     return histeditstate(repo, parentctxnode, rules,
       
   794         keep, topmost, replacements)
   787 
   795 
   788 def makedesc(c):
   796 def makedesc(c):
   789     """build a initial action line for a ctx `c`
   797     """build a initial action line for a ctx `c`
   790 
   798 
   791     line are in the form:
   799     line are in the form:
   948         release(lock)
   956         release(lock)
   949 
   957 
   950 def summaryhook(ui, repo):
   958 def summaryhook(ui, repo):
   951     if not os.path.exists(repo.join('histedit-state')):
   959     if not os.path.exists(repo.join('histedit-state')):
   952         return
   960         return
   953     (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
   961     state = readstate(repo)
   954     if rules:
   962     if state.rules:
   955         # i18n: column positioning for "hg summary"
   963         # i18n: column positioning for "hg summary"
   956         ui.write(_('hist:   %s (histedit --continue)\n') %
   964         ui.write(_('hist:   %s (histedit --continue)\n') %
   957                  (ui.label(_('%d remaining'), 'histedit.remaining') %
   965                  (ui.label(_('%d remaining'), 'histedit.remaining') %
   958                   len(rules)))
   966                   len(state.rules)))
   959 
   967 
   960 def extsetup(ui):
   968 def extsetup(ui):
   961     cmdutil.summaryhooks.add('histedit', summaryhook)
   969     cmdutil.summaryhooks.add('histedit', summaryhook)
   962     cmdutil.unfinishedstates.append(
   970     cmdutil.unfinishedstates.append(
   963         ['histedit-state', False, True, _('histedit in progress'),
   971         ['histedit-state', False, True, _('histedit in progress'),