67 from mercurial.node import nullid |
69 from mercurial.node import nullid |
68 from mercurial import wireproto |
70 from mercurial import wireproto |
69 from mercurial import localrepo |
71 from mercurial import localrepo |
70 from mercurial.hgweb import hgweb_mod |
72 from mercurial.hgweb import hgweb_mod |
71 from mercurial import bundle2 |
73 from mercurial import bundle2 |
|
74 from mercurial import util |
72 |
75 |
73 cmdtable = {} |
76 cmdtable = {} |
74 command = cmdutil.command(cmdtable) |
77 command = cmdutil.command(cmdtable) |
75 |
78 |
76 _pack = struct.pack |
79 _pack = struct.pack |
374 ui.setconfig('alias', 'olog', "log -r 'precursors(.)' --hidden") |
377 ui.setconfig('alias', 'olog', "log -r 'precursors(.)' --hidden") |
375 if ui.config('alias', 'odiff', None) is None: |
378 if ui.config('alias', 'odiff', None) is None: |
376 ui.setconfig('alias', 'odiff', |
379 ui.setconfig('alias', 'odiff', |
377 "diff --hidden --rev 'limit(precursors(.),1)' --rev .") |
380 "diff --hidden --rev 'limit(precursors(.),1)' --rev .") |
378 if ui.config('alias', 'grab', None) is None: |
381 if ui.config('alias', 'grab', None) is None: |
379 ui.setconfig('alias', 'grab', |
382 if os.name == 'nt': |
380 "! $HG rebase --dest . --rev $@ && $HG up tip") |
383 ui.setconfig('alias', 'grab', |
|
384 "! " + util.hgexecutable() + " rebase --dest . --rev && " |
|
385 + util.hgexecutable() + " up tip") |
|
386 else: |
|
387 ui.setconfig('alias', 'grab', |
|
388 "! $HG rebase --dest . --rev $@ && $HG up tip") |
381 |
389 |
382 |
390 |
383 ### Troubled revset symbol |
391 ### Troubled revset symbol |
384 |
392 |
385 @eh.revset('troubled') |
393 @eh.revset('troubled') |
774 'no support for evolving merge changesets yet', |
782 'no support for evolving merge changesets yet', |
775 hint="Redo the merge and use `hg prune` to obsolete the old one") |
783 hint="Redo the merge and use `hg prune` to obsolete the old one") |
776 destbookmarks = repo.nodebookmarks(dest.node()) |
784 destbookmarks = repo.nodebookmarks(dest.node()) |
777 nodesrc = orig.node() |
785 nodesrc = orig.node() |
778 destphase = repo[nodesrc].phase() |
786 destphase = repo[nodesrc].phase() |
|
787 commitmsg = orig.description() |
|
788 |
|
789 cache = {} |
|
790 sha1s = re.findall(sha1re, commitmsg) |
|
791 unfi = repo.unfiltered() |
|
792 for sha1 in sha1s: |
|
793 ctx = None |
|
794 try: |
|
795 ctx = unfi[sha1] |
|
796 except error.RepoLookupError: |
|
797 continue |
|
798 |
|
799 if not ctx.obsolete(): |
|
800 continue |
|
801 |
|
802 successors = obsolete.successorssets(repo, ctx.node(), cache) |
|
803 |
|
804 # We can't make any assumptions about how to update the hash if the |
|
805 # cset in question was split or diverged. |
|
806 if len(successors) == 1 and len(successors[0]) == 1: |
|
807 newsha1 = node.hex(successors[0][0]) |
|
808 commitmsg = commitmsg.replace(sha1, newsha1[:len(sha1)]) |
|
809 else: |
|
810 repo.ui.note(_('The stale commit message reference to %s could ' |
|
811 'not be updated') % sha1) |
|
812 |
779 tr = repo.transaction('relocate') |
813 tr = repo.transaction('relocate') |
780 try: |
814 try: |
781 try: |
815 try: |
782 r = rebase.rebasenode(repo, orig.node(), dest.node(), |
816 r = rebase.rebasenode(repo, orig.node(), dest.node(), |
783 {node.nullrev: node.nullrev}, False) |
817 {node.nullrev: node.nullrev}, False) |
784 if r[-1]: #some conflict |
818 if r[-1]: #some conflict |
785 raise util.Abort( |
819 raise util.Abort( |
786 'unresolved merge conflicts (see hg help resolve)') |
820 'unresolved merge conflicts (see hg help resolve)') |
787 cmdutil.duplicatecopies(repo, orig.node(), dest.node()) |
821 cmdutil.duplicatecopies(repo, orig.node(), dest.node()) |
788 nodenew = rebase.concludenode(repo, orig.node(), dest.node(), |
822 nodenew = rebase.concludenode(repo, orig.node(), dest.node(), |
789 node.nullid) |
823 node.nullid, commitmsg) |
790 except util.Abort, exc: |
824 except util.Abort, exc: |
791 class LocalMergeFailure(MergeFailure, exc.__class__): |
825 class LocalMergeFailure(MergeFailure, exc.__class__): |
792 pass |
826 pass |
793 exc.__class__ = LocalMergeFailure |
827 exc.__class__ = LocalMergeFailure |
794 raise |
828 raise |
1110 allopt = opts['all'] |
1144 allopt = opts['all'] |
1111 dryrunopt = opts['dry_run'] |
1145 dryrunopt = opts['dry_run'] |
1112 confirmopt = opts['confirm'] |
1146 confirmopt = opts['confirm'] |
1113 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'evolve') |
1147 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'evolve') |
1114 |
1148 |
|
1149 startnode = repo['.'] |
|
1150 |
1115 if contopt: |
1151 if contopt: |
1116 if anyopt: |
1152 if anyopt: |
1117 raise util.Abort('cannot specify both "--any" and "--continue"') |
1153 raise util.Abort('cannot specify both "--any" and "--continue"') |
1118 if allopt: |
1154 if allopt: |
1119 raise util.Abort('cannot specify both "--all" and "--continue"') |
1155 raise util.Abort('cannot specify both "--all" and "--continue"') |
1153 |
1189 |
1154 if dryrunopt: |
1190 if dryrunopt: |
1155 print 'hg update %s' % ctx.rev() |
1191 print 'hg update %s' % ctx.rev() |
1156 return 0 |
1192 return 0 |
1157 else: |
1193 else: |
1158 return hg.update(repo, ctx.rev()) |
1194 res = hg.update(repo, ctx.rev()) |
|
1195 if ctx != startnode: |
|
1196 ui.status(_('working directory is now at %s\n') % ctx) |
|
1197 return res |
1159 |
1198 |
1160 troubled = repo.revs('troubled()') |
1199 troubled = repo.revs('troubled()') |
1161 if troubled: |
1200 if troubled: |
1162 ui.write_err(_('nothing to evolve here\n')) |
1201 ui.write_err(_('nothing to evolve here\n')) |
1163 ui.status(_('(%i troubled changesets, do you want --any ?)\n') |
1202 ui.status(_('(%i troubled changesets, do you want --any ?)\n') |
1186 finally: |
1225 finally: |
1187 lockmod.release(tr, lock, wlock) |
1226 lockmod.release(tr, lock, wlock) |
1188 progresscb() |
1227 progresscb() |
1189 seen += 1 |
1228 seen += 1 |
1190 if not allopt: |
1229 if not allopt: |
|
1230 if repo['.'] != startnode: |
|
1231 ui.status(_('working directory is now at %s\n') % repo['.']) |
1191 return result |
1232 return result |
1192 progresscb() |
1233 progresscb() |
1193 tro = _picknexttroubled(ui, repo, anyopt or allopt) |
1234 tro = _picknexttroubled(ui, repo, anyopt or allopt) |
1194 |
1235 |
1195 if allopt: |
1236 if allopt: |
1196 ui.progress('evolve', None) |
1237 ui.progress('evolve', None) |
|
1238 |
|
1239 if repo['.'] != startnode: |
|
1240 ui.status(_('working directory is now at %s\n') % repo['.']) |
1197 |
1241 |
1198 |
1242 |
1199 def _evolveany(ui, repo, tro, dryrunopt, confirmopt, progresscb): |
1243 def _evolveany(ui, repo, tro, dryrunopt, confirmopt, progresscb): |
1200 repo = repo.unfiltered() |
1244 repo = repo.unfiltered() |
1201 tro = repo[tro.rev()] |
1245 tro = repo[tro.rev()] |
1731 ui.status(_('working directory now at %s\n') % newnode) |
1775 ui.status(_('working directory now at %s\n') % newnode) |
1732 # update bookmarks |
1776 # update bookmarks |
1733 if bookmark: |
1777 if bookmark: |
1734 _deletebookmark(ui, marks, bookmark) |
1778 _deletebookmark(ui, marks, bookmark) |
1735 for ctx in repo.unfiltered().set('bookmark() and %ld', precs): |
1779 for ctx in repo.unfiltered().set('bookmark() and %ld', precs): |
1736 ldest = list(repo.set('max((::%d) - obsolete())', ctx)) |
1780 # used to be: |
1737 if ldest: |
1781 # |
1738 dest = ldest[0] |
1782 # ldest = list(repo.set('max((::%d) - obsolete())', ctx)) |
1739 updatebookmarks = _bookmarksupdater(repo, ctx.node()) |
1783 # if ldest: |
1740 updatebookmarks(dest.node()) |
1784 # c = ldest[0] |
|
1785 # |
|
1786 # but then revset took a lazy arrow in the knee and became much |
|
1787 # slower. The new forms makes as much sense and a much faster. |
|
1788 for dest in ctx.ancestors(): |
|
1789 if not dest.obsolete(): |
|
1790 updatebookmarks = _bookmarksupdater(repo, ctx.node()) |
|
1791 updatebookmarks(dest.node()) |
|
1792 break |
1741 finally: |
1793 finally: |
1742 lockmod.release(lock, wlock) |
1794 lockmod.release(lock, wlock) |
1743 |
1795 |
1744 @command('amend|refresh', |
1796 @command('amend|refresh', |
1745 [('A', 'addremove', None, |
1797 [('A', 'addremove', None, |