890 tr.close() |
891 tr.close() |
891 return newid, created |
892 return newid, created |
892 finally: |
893 finally: |
893 lockmod.release(lock, wlock, tr) |
894 lockmod.release(lock, wlock, tr) |
894 |
895 |
895 class MergeFailure(util.Abort): |
896 class MergeFailure(error.Abort): |
896 pass |
897 pass |
897 |
898 |
898 def relocate(repo, orig, dest, keepbranch=False): |
899 def relocate(repo, orig, dest, keepbranch=False): |
899 """rewrite <rev> on dest""" |
900 """rewrite <rev> on dest""" |
900 if orig.rev() == dest.rev(): |
901 if orig.rev() == dest.rev(): |
901 raise util.Abort(_('tried to relocate a node on top of itself'), |
902 raise error.Abort(_('tried to relocate a node on top of itself'), |
902 hint=_("This shouldn't happen. If you still " |
903 hint=_("This shouldn't happen. If you still " |
903 "need to move changesets, please do so " |
904 "need to move changesets, please do so " |
904 "manually with nothing to rebase - working " |
905 "manually with nothing to rebase - working " |
905 "directory parent is also destination")) |
906 "directory parent is also destination")) |
906 |
907 |
907 if not orig.p2().rev() == node.nullrev: |
908 if not orig.p2().rev() == node.nullrev: |
908 raise util.Abort( |
909 raise error.Abort( |
909 'no support for evolving merge changesets yet', |
910 'no support for evolving merge changesets yet', |
910 hint="Redo the merge and use `hg prune <old> --succ <new>` to obsolete the old one") |
911 hint="Redo the merge and use `hg prune <old> --succ <new>` " |
|
912 "to obsolete the old one") |
911 destbookmarks = repo.nodebookmarks(dest.node()) |
913 destbookmarks = repo.nodebookmarks(dest.node()) |
912 nodesrc = orig.node() |
914 nodesrc = orig.node() |
913 destphase = repo[nodesrc].phase() |
915 destphase = repo[nodesrc].phase() |
914 commitmsg = orig.description() |
916 commitmsg = orig.description() |
915 |
917 |
1225 # same with parent data |
1227 # same with parent data |
1226 for c in pclustersmap.values(): |
1228 for c in pclustersmap.values(): |
1227 fc = (frozenset(c[0]), frozenset(c[1])) |
1229 fc = (frozenset(c[0]), frozenset(c[1])) |
1228 for n in fc[0]: |
1230 for n in fc[0]: |
1229 pclustersmap[n] = fc |
1231 pclustersmap[n] = fc |
1230 ui.write(' for known precursors: %9i\n' % known) |
1232 ui.write((' for known precursors: %9i\n' % known)) |
1231 ui.write(' with parents data: %9i\n' % parentsdata) |
1233 ui.write((' with parents data: %9i\n' % parentsdata)) |
1232 # successors data |
1234 # successors data |
1233 ui.write('markers with no successors: %9i\n' % sucscount[0]) |
1235 ui.write(('markers with no successors: %9i\n' % sucscount[0])) |
1234 ui.write(' 1 successors: %9i\n' % sucscount[1]) |
1236 ui.write((' 1 successors: %9i\n' % sucscount[1])) |
1235 ui.write(' 2 successors: %9i\n' % sucscount[2]) |
1237 ui.write((' 2 successors: %9i\n' % sucscount[2])) |
1236 ui.write(' more than 2 successors: %9i\n' % sucscount[3]) |
1238 ui.write((' more than 2 successors: %9i\n' % sucscount[3])) |
1237 # meta data info |
1239 # meta data info |
1238 ui.write(' available keys:\n') |
1240 ui.write((' available keys:\n')) |
1239 for key in sorted(metakeys): |
1241 for key in sorted(metakeys): |
1240 ui.write(' %15s: %9i\n' % (key, metakeys[key])) |
1242 ui.write((' %15s: %9i\n' % (key, metakeys[key]))) |
1241 |
1243 |
1242 allclusters = list(set(clustersmap.values())) |
1244 allclusters = list(set(clustersmap.values())) |
1243 allclusters.sort(key=lambda x: len(x[1])) |
1245 allclusters.sort(key=lambda x: len(x[1])) |
1244 ui.write('disconnected clusters: %9i\n' % len(allclusters)) |
1246 ui.write(('disconnected clusters: %9i\n' % len(allclusters))) |
1245 |
1247 |
1246 ui.write(' any known node: %9i\n' |
1248 ui.write(' any known node: %9i\n' |
1247 % len([c for c in allclusters |
1249 % len([c for c in allclusters |
1248 if [n for n in c[0] if nm.get(n) is not None]])) |
1250 if [n for n in c[0] if nm.get(n) is not None]])) |
1249 if allclusters: |
1251 if allclusters: |
1250 nbcluster = len(allclusters) |
1252 nbcluster = len(allclusters) |
1251 ui.write(' smallest length: %9i\n' % len(allclusters[0][1])) |
1253 ui.write((' smallest length: %9i\n' % len(allclusters[0][1]))) |
1252 ui.write(' longer length: %9i\n' % len(allclusters[-1][1])) |
1254 ui.write((' longer length: %9i\n' |
|
1255 % len(allclusters[-1][1]))) |
1253 median = len(allclusters[nbcluster//2][1]) |
1256 median = len(allclusters[nbcluster//2][1]) |
1254 ui.write(' median length: %9i\n' % median) |
1257 ui.write((' median length: %9i\n' % median)) |
1255 mean = sum(len(x[1]) for x in allclusters) // nbcluster |
1258 mean = sum(len(x[1]) for x in allclusters) // nbcluster |
1256 ui.write(' mean length: %9i\n' % mean) |
1259 ui.write((' mean length: %9i\n' % mean)) |
1257 allpclusters = list(set(pclustersmap.values())) |
1260 allpclusters = list(set(pclustersmap.values())) |
1258 allpclusters.sort(key=lambda x: len(x[1])) |
1261 allpclusters.sort(key=lambda x: len(x[1])) |
1259 ui.write(' using parents data: %9i\n' % len(allpclusters)) |
1262 ui.write((' using parents data: %9i\n' % len(allpclusters))) |
1260 ui.write(' any known node: %9i\n' |
1263 ui.write(' any known node: %9i\n' |
1261 % len([c for c in allclusters |
1264 % len([c for c in allclusters |
1262 if [n for n in c[0] if nm.get(n) is not None]])) |
1265 if [n for n in c[0] if nm.get(n) is not None]])) |
1263 if allpclusters: |
1266 if allpclusters: |
1264 nbcluster = len(allpclusters) |
1267 nbcluster = len(allpclusters) |
1265 ui.write(' smallest length: %9i\n' % len(allpclusters[0][1])) |
1268 ui.write((' smallest length: %9i\n' |
1266 ui.write(' longer length: %9i\n' % len(allpclusters[-1][1])) |
1269 % len(allpclusters[0][1]))) |
|
1270 ui.write((' longer length: %9i\n' |
|
1271 % len(allpclusters[-1][1]))) |
1267 median = len(allpclusters[nbcluster//2][1]) |
1272 median = len(allpclusters[nbcluster//2][1]) |
1268 ui.write(' median length: %9i\n' % median) |
1273 ui.write((' median length: %9i\n' % median)) |
1269 mean = sum(len(x[1]) for x in allpclusters) // nbcluster |
1274 mean = sum(len(x[1]) for x in allpclusters) // nbcluster |
1270 ui.write(' mean length: %9i\n' % mean) |
1275 ui.write((' mean length: %9i\n' % mean)) |
1271 |
1276 |
1272 def _solveone(ui, repo, ctx, dryrun, confirm, progresscb, category): |
1277 def _solveone(ui, repo, ctx, dryrun, confirm, progresscb, category): |
1273 """Resolve the troubles affecting one revision""" |
1278 """Resolve the troubles affecting one revision""" |
1274 wlock = lock = tr = None |
1279 wlock = lock = tr = None |
1275 try: |
1280 try: |
1531 @command('^evolve|stabilize|solve', |
1537 @command('^evolve|stabilize|solve', |
1532 [('n', 'dry-run', False, |
1538 [('n', 'dry-run', False, |
1533 _('do not perform actions, just print what would be done')), |
1539 _('do not perform actions, just print what would be done')), |
1534 ('', 'confirm', False, |
1540 ('', 'confirm', False, |
1535 _('ask for confirmation before performing the action')), |
1541 _('ask for confirmation before performing the action')), |
1536 ('A', 'any', False, _('also consider troubled changesets unrelated to current working directory')), |
1542 ('A', 'any', False, |
|
1543 _('also consider troubled changesets unrelated to current working ' |
|
1544 'directory')), |
1537 ('r', 'rev', [], _('solves troubles of these revisions')), |
1545 ('r', 'rev', [], _('solves troubles of these revisions')), |
1538 ('', 'bumped', False, _('solves only bumped changesets')), |
1546 ('', 'bumped', False, _('solves only bumped changesets')), |
1539 ('', 'divergent', False, _('solves only divergent changesets')), |
1547 ('', 'divergent', False, _('solves only divergent changesets')), |
1540 ('', 'unstable', False, _('solves only unstable changesets (default)')), |
1548 ('', 'unstable', False, _('solves only unstable changesets (default)')), |
1541 ('a', 'all', False, _('evolve all troubled changesets related to the current ' |
1549 ('a', 'all', False, _('evolve all troubled changesets related to the ' |
1542 'working directory and its descendants')), |
1550 'current working directory and its descendants')), |
1543 ('c', 'continue', False, _('continue an interrupted evolution')), |
1551 ('c', 'continue', False, _('continue an interrupted evolution')), |
1544 ] + mergetoolopts, |
1552 ] + mergetoolopts, |
1545 _('[OPTIONS]...')) |
1553 _('[OPTIONS]...')) |
1546 def evolve(ui, repo, **opts): |
1554 def evolve(ui, repo, **opts): |
1547 """solve troubled changesets in your repository |
1555 """solve troubled changesets in your repository |
1548 |
1556 |
1549 Modifying history can lead to various types of troubled changesets: unstable, |
1557 Modifying history can lead to various types of troubled changesets: |
1550 bumped, or divergent. The evolve command resolves your troubles by executing one |
1558 unstable, bumped, or divergent. The evolve command resolves your troubles |
1551 of the following actions: |
1559 by executing one of the following actions: |
1552 |
1560 |
1553 - update working copy to a successor |
1561 - update working copy to a successor |
1554 - rebase an unstable changeset |
1562 - rebase an unstable changeset |
1555 - extract the desired changes from a bumped changeset |
1563 - extract the desired changes from a bumped changeset |
1556 - fuse divergent changesets back together |
1564 - fuse divergent changesets back together |
1557 |
1565 |
1558 If you pass no arguments, evolve works in automatic mode: it will execute a |
1566 If you pass no arguments, evolve works in automatic mode: it will execute a |
1559 single action to reduce instability related to your working copy. There are two |
1567 single action to reduce instability related to your working copy. There are |
1560 cases for this action. First, if the parent of your working copy is obsolete, |
1568 two cases for this action. First, if the parent of your working copy is |
1561 evolve updates to the parent's successor. Second, if the working copy parent is |
1569 obsolete, evolve updates to the parent's successor. Second, if the working |
1562 not obsolete but has obsolete predecessors, then evolve determines if there is an |
1570 copy parent is not obsolete but has obsolete predecessors, then evolve |
1563 unstable changeset that can be rebased onto the working copy parent in order to |
1571 determines if there is an unstable changeset that can be rebased onto the |
1564 reduce instability. If so, evolve rebases that changeset. If not, evolve refuses |
1572 working copy parent in order to reduce instability. |
1565 to guess your intention, and gives a hint about what you might want to do next. |
1573 If so, evolve rebases that changeset. If not, evolve refuses to guess your |
|
1574 intention, and gives a hint about what you might want to do next. |
1566 |
1575 |
1567 Any time evolve creates a changeset, it updates the working copy to the new |
1576 Any time evolve creates a changeset, it updates the working copy to the new |
1568 changeset. (Currently, every successful evolve operation involves an update as |
1577 changeset. (Currently, every successful evolve operation involves an update |
1569 well; this may change in future.) |
1578 as well; this may change in future.) |
1570 |
1579 |
1571 Automatic mode only handles common use cases. For example, it avoids taking |
1580 Automatic mode only handles common use cases. For example, it avoids taking |
1572 action in the case of ambiguity, and it ignores unstable changesets that are not |
1581 action in the case of ambiguity, and it ignores unstable changesets that |
1573 related to your working copy. It also refuses to solve bumped or divergent |
1582 are not related to your working copy. |
1574 changesets unless you explicity request such behavior (see below). |
1583 It also refuses to solve bumped or divergent changesets unless you explicity |
|
1584 request such behavior (see below). |
1575 |
1585 |
1576 Eliminating all instability around your working copy may require multiple |
1586 Eliminating all instability around your working copy may require multiple |
1577 invocations of :hg:`evolve`. Alternately, use ``--all`` to recursively select and |
1587 invocations of :hg:`evolve`. Alternately, use ``--all`` to recursively |
1578 evolve all unstable changesets that can be rebased onto the working copy parent. |
1588 select and evolve all unstable changesets that can be rebased onto the |
|
1589 working copy parent. |
1579 This is more powerful than successive invocations, since ``--all`` handles |
1590 This is more powerful than successive invocations, since ``--all`` handles |
1580 ambiguous cases (e.g. unstable changesets with multiple children) by evolving all |
1591 ambiguous cases (e.g. unstable changesets with multiple children) by |
1581 branches. |
1592 evolving all branches. |
1582 |
1593 |
1583 When your repository cannot be handled by automatic mode, you might need to use |
1594 When your repository cannot be handled by automatic mode, you might need to |
1584 ``--rev`` to specify a changeset to evolve. For example, if you have an unstable |
1595 use ``--rev`` to specify a changeset to evolve. For example, if you have |
1585 changeset that is not related to the working copy parent, you could use ``--rev`` |
1596 an unstable changeset that is not related to the working copy parent, |
1586 to evolve it. Or, if some changeset has multiple unstable children, evolve in |
1597 you could use ``--rev`` to evolve it. Or, if some changeset has multiple |
1587 automatic mode refuses to guess which one to evolve; you have to use ``--rev`` |
1598 unstable children, evolve in automatic mode refuses to guess which one to |
1588 in that case. |
1599 evolve; you have to use ``--rev`` in that case. |
1589 |
1600 |
1590 Alternately, ``--any`` makes evolve search for the next evolvable changeset |
1601 Alternately, ``--any`` makes evolve search for the next evolvable changeset |
1591 regardless of whether it is related to the working copy parent. |
1602 regardless of whether it is related to the working copy parent. |
1592 |
1603 |
1593 You can supply multiple revisions to evolve multiple troubled changesets in a |
1604 You can supply multiple revisions to evolve multiple troubled changesets |
1594 single invocation. In revset terms, ``--any`` is equivalent to ``--rev |
1605 in a single invocation. In revset terms, ``--any`` is equivalent to ``--rev |
1595 first(unstable())``. ``--rev`` and ``--all`` are mutually exclusive, as are |
1606 first(unstable())``. ``--rev`` and ``--all`` are mutually exclusive, as are |
1596 ``--rev`` and ``--any``. |
1607 ``--rev`` and ``--any``. |
1597 |
1608 |
1598 ``hg evolve --any --all`` is useful for cleaning up instability across all |
1609 ``hg evolve --any --all`` is useful for cleaning up instability across all |
1599 branches, letting evolve figure out the appropriate order and destination. |
1610 branches, letting evolve figure out the appropriate order and destination. |
1600 |
1611 |
1601 When you have troubled changesets that are not unstable, :hg:`evolve` refuses to |
1612 When you have troubled changesets that are not unstable, :hg:`evolve` |
1602 consider them unless you specify the category of trouble you wish to resolve, |
1613 refuses to consider them unless you specify the category of trouble you |
1603 with ``--bumped`` or ``--divergent``. These options are currently mutually |
1614 wish to resolve, with ``--bumped`` or ``--divergent``. These options are |
1604 exclusive with each other and with ``--unstable`` (the default). You can combine |
1615 currently mutually exclusive with each other and with ``--unstable`` |
1605 ``--bumped`` or ``--divergent`` with ``--rev``, ``--all``, or ``--any``. |
1616 (the default). You can combine ``--bumped`` or ``--divergent`` with |
|
1617 ``--rev``, ``--all``, or ``--any``. |
1606 |
1618 |
1607 """ |
1619 """ |
1608 |
1620 |
1609 # Options |
1621 # Options |
1610 contopt = opts['continue'] |
1622 contopt = opts['continue'] |
1654 count = allopt and len(troubled) or 1 |
1667 count = allopt and len(troubled) or 1 |
1655 showprogress = allopt |
1668 showprogress = allopt |
1656 |
1669 |
1657 def progresscb(): |
1670 def progresscb(): |
1658 if revopt or allopt: |
1671 if revopt or allopt: |
1659 ui.progress('evolve', seen, unit='changesets', total=count) |
1672 ui.progress(_('evolve'), seen, unit='changesets', total=count) |
1660 |
1673 |
1661 # Continuation handling |
1674 # Continuation handling |
1662 if contopt: |
1675 if contopt: |
1663 if anyopt: |
1676 if anyopt: |
1664 raise util.Abort('cannot specify both "--any" and "--continue"') |
1677 raise error.Abort('cannot specify both "--any" and "--continue"') |
1665 if allopt: |
1678 if allopt: |
1666 raise util.Abort('cannot specify both "--all" and "--continue"') |
1679 raise error.Abort('cannot specify both "--all" and "--continue"') |
1667 graftcmd = commands.table['graft'][0] |
1680 graftcmd = commands.table['graft'][0] |
1668 return graftcmd(ui, repo, old_obsolete=True, **{'continue': True}) |
1681 return graftcmd(ui, repo, old_obsolete=True, **{'continue': True}) |
1669 cmdutil.bailifchanged(repo) |
1682 cmdutil.bailifchanged(repo) |
1670 |
1683 |
1671 |
1684 |
1672 if revopt and allopt: |
1685 if revopt and allopt: |
1673 raise util.Abort('cannot specify both "--rev" and "--all"') |
1686 raise error.Abort('cannot specify both "--rev" and "--all"') |
1674 if revopt and anyopt: |
1687 if revopt and anyopt: |
1675 raise util.Abort('cannot specify both "--rev" and "--any"') |
1688 raise error.Abort('cannot specify both "--rev" and "--any"') |
1676 |
1689 |
1677 revs = _selectrevs(repo, allopt, revopt, anyopt, targetcat) |
1690 revs = _selectrevs(repo, allopt, revopt, anyopt, targetcat) |
1678 |
1691 |
1679 if not revs: |
1692 if not revs: |
1680 return _handlenotrouble(ui, repo, allopt, revopt, anyopt, targetcat) |
1693 return _handlenotrouble(ui, repo, allopt, revopt, anyopt, targetcat) |
1819 ui.write_err(msg) |
1833 ui.write_err(msg) |
1820 return 2 |
1834 return 2 |
1821 prec = repo.set('last(allprecursors(%d) and public())', bumped).next() |
1835 prec = repo.set('last(allprecursors(%d) and public())', bumped).next() |
1822 # For now we deny target merge |
1836 # For now we deny target merge |
1823 if len(prec.parents()) > 1: |
1837 if len(prec.parents()) > 1: |
1824 msg = _('skipping: %s: public version is a merge, this not handled yet\n') % prec |
1838 msg = _('skipping: %s: public version is a merge, ' |
|
1839 'this is not handled yet\n') % prec |
1825 ui.write_err(msg) |
1840 ui.write_err(msg) |
1826 return 2 |
1841 return 2 |
1827 |
1842 |
1828 displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) |
1843 displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) |
1829 if not ui.quiet or confirm: |
1844 if not ui.quiet or confirm: |
1830 repo.ui.write(_('recreate:')) |
1845 repo.ui.write(_('recreate:')) |
1831 displayer.show(bumped) |
1846 displayer.show(bumped) |
1832 repo.ui.write(_('atop:')) |
1847 repo.ui.write(_('atop:')) |
1833 displayer.show(prec) |
1848 displayer.show(prec) |
1834 if confirm and ui.prompt('perform evolve? [Ny]', 'n') != 'y': |
1849 if confirm and ui.prompt('perform evolve? [Ny]', 'n') != 'y': |
1835 raise util.Abort(_('evolve aborted by user')) |
1850 raise error.Abort(_('evolve aborted by user')) |
1836 if dryrun: |
1851 if dryrun: |
1837 todo = 'hg rebase --rev %s --dest %s;\n' % (bumped, prec.p1()) |
1852 todo = 'hg rebase --rev %s --dest %s;\n' % (bumped, prec.p1()) |
1838 repo.ui.write(todo) |
1853 repo.ui.write(todo) |
1839 repo.ui.write('hg update %s;\n' % prec) |
1854 repo.ui.write(('hg update %s;\n' % prec)) |
1840 repo.ui.write('hg revert --all --rev %s;\n' % bumped) |
1855 repo.ui.write(('hg revert --all --rev %s;\n' % bumped)) |
1841 repo.ui.write('hg commit --msg "bumped update to %s"') |
1856 repo.ui.write(('hg commit --msg "bumped update to %s"')) |
1842 return 0 |
1857 return 0 |
1843 if progresscb: progresscb() |
1858 if progresscb: progresscb() |
1844 newid = tmpctx = None |
1859 newid = tmpctx = None |
1845 tmpctx = bumped |
1860 tmpctx = bumped |
1846 # Basic check for common parent. Far too complicated and fragile |
1861 # Basic check for common parent. Far too complicated and fragile |
1924 repo = repo.unfiltered() |
1939 repo = repo.unfiltered() |
1925 divergent = repo[divergent.rev()] |
1940 divergent = repo[divergent.rev()] |
1926 base, others = divergentdata(divergent) |
1941 base, others = divergentdata(divergent) |
1927 if len(others) > 1: |
1942 if len(others) > 1: |
1928 othersstr = "[%s]" % (','.join([str(i) for i in others])) |
1943 othersstr = "[%s]" % (','.join([str(i) for i in others])) |
1929 msg = _("skipping %d:divergent with a changeset that got splitted into multiple ones:\n" |
1944 msg = _("skipping %d:divergent with a changeset that got splitted" |
|
1945 " into multiple ones:\n" |
1930 "|[%s]\n" |
1946 "|[%s]\n" |
1931 "| This is not handled by automatic evolution yet\n" |
1947 "| This is not handled by automatic evolution yet\n" |
1932 "| You have to fallback to manual handling with commands " |
1948 "| You have to fallback to manual handling with commands " |
1933 "such as:\n" |
1949 "such as:\n" |
1934 "| - hg touch -D\n" |
1950 "| - hg touch -D\n" |
1935 "| - hg prune\n" |
1951 "| - hg prune\n" |
1936 "| \n" |
1952 "| \n" |
1937 "| You should contact your local evolution Guru for help.\n" |
1953 "| You should contact your local evolution Guru for help.\n" |
1938 % (divergent, othersstr)) |
1954 ) % (divergent, othersstr) |
1939 ui.write_err(msg) |
1955 ui.write_err(msg) |
1940 return 2 |
1956 return 2 |
1941 other = others[0] |
1957 other = others[0] |
1942 if len(other.parents()) > 1: |
1958 if len(other.parents()) > 1: |
1943 msg = _("skipping %s: divergent changeset can't be a merge (yet)\n" % divergent) |
1959 msg = _("skipping %s: divergent changeset can't be " |
|
1960 "a merge (yet)\n") % divergent |
1944 ui.write_err(msg) |
1961 ui.write_err(msg) |
1945 hint = _("You have to fallback to solving this by hand...\n" |
1962 hint = _("You have to fallback to solving this by hand...\n" |
1946 "| This probably means redoing the merge and using \n" |
1963 "| This probably means redoing the merge and using \n" |
1947 "| `hg prune` to kill older version.\n") |
1964 "| `hg prune` to kill older version.\n") |
1948 ui.write_err(hint) |
1965 ui.write_err(hint) |
1949 return 2 |
1966 return 2 |
1950 if other.p1() not in divergent.parents(): |
1967 if other.p1() not in divergent.parents(): |
1951 msg = _("skipping %s: have a different parent than %s (not handled yet)\n") % (divergent, other) |
1968 msg = _("skipping %s: have a different parent than %s " |
|
1969 "(not handled yet)\n") % (divergent, other) |
1952 hint = _("| %(d)s, %(o)s are not based on the same changeset.\n" |
1970 hint = _("| %(d)s, %(o)s are not based on the same changeset.\n" |
1953 "| With the current state of its implementation, \n" |
1971 "| With the current state of its implementation, \n" |
1954 "| evolve does not work in that case.\n" |
1972 "| evolve does not work in that case.\n" |
1955 "| rebase one of them next to the other and run \n" |
1973 "| rebase one of them next to the other and run \n" |
1956 "| this command again.\n" |
1974 "| this command again.\n" |
1957 "| - either: hg rebase --dest 'p1(%(d)s)' -r %(o)s\n" |
1975 "| - either: hg rebase --dest 'p1(%(d)s)' -r %(o)s\n" |
1958 "| - or: hg rebase --dest 'p1(%(o)s)' -r %(d)s\n" |
1976 "| - or: hg rebase --dest 'p1(%(o)s)' -r %(d)s\n" |
1959 % {'d': divergent, 'o': other}) |
1977 ) % {'d': divergent, 'o': other} |
1960 ui.write_err(msg) |
1978 ui.write_err(msg) |
1961 ui.write_err(hint) |
1979 ui.write_err(hint) |
1962 return 2 |
1980 return 2 |
1963 |
1981 |
1964 displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) |
1982 displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) |
2041 newer = obsolete.successorssets(ctx._repo, base.node()) |
2059 newer = obsolete.successorssets(ctx._repo, base.node()) |
2042 # drop filter and solution including the original ctx |
2060 # drop filter and solution including the original ctx |
2043 newer = [n for n in newer if n and ctx.node() not in n] |
2061 newer = [n for n in newer if n and ctx.node() not in n] |
2044 if newer: |
2062 if newer: |
2045 return base, tuple(ctx._repo[o] for o in newer[0]) |
2063 return base, tuple(ctx._repo[o] for o in newer[0]) |
2046 raise util.Abort("base of divergent changeset %s not found" % ctx, |
2064 raise error.Abort("base of divergent changeset %s not found" % ctx, |
2047 hint='this case is not yet handled') |
2065 hint='this case is not yet handled') |
2048 |
2066 |
2049 |
2067 |
2050 |
2068 |
2051 shorttemplate = '[{rev}] {desc|firstline}\n' |
2069 shorttemplate = '[{rev}] {desc|firstline}\n' |
2052 |
2070 |
2053 @command('^previous', |
2071 @command('^previous', |
2054 [('B', 'move-bookmark', False, |
2072 [('B', 'move-bookmark', False, |
2055 _('move active bookmark after update')), |
2073 _('move active bookmark after update')), |
2056 ('', 'merge', False, _('bring uncommitted change along')), |
2074 ('', 'merge', False, _('bring uncommitted change along')), |
2057 ('n', 'dry-run', False, _('do not perform actions, just print what would be done'))], |
2075 ('n', 'dry-run', False, |
|
2076 _('do not perform actions, just print what would be done'))], |
2058 '[OPTION]...') |
2077 '[OPTION]...') |
2059 def cmdprevious(ui, repo, **opts): |
2078 def cmdprevious(ui, repo, **opts): |
2060 """update to parent and display summary lines""" |
2079 """update to parent and display summary lines""" |
2061 wkctx = repo[None] |
2080 wkctx = repo[None] |
2062 wparents = wkctx.parents() |
2081 wparents = wkctx.parents() |
2063 dryrunopt = opts['dry_run'] |
2082 dryrunopt = opts['dry_run'] |
2064 if len(wparents) != 1: |
2083 if len(wparents) != 1: |
2065 raise util.Abort('merge in progress') |
2084 raise error.Abort('merge in progress') |
2066 if not opts['merge']: |
2085 if not opts['merge']: |
2067 try: |
2086 try: |
2068 cmdutil.bailifchanged(repo) |
2087 cmdutil.bailifchanged(repo) |
2069 except error.Abort, exc: |
2088 except error.Abort as exc: |
2070 exc.hint = _('do you want --merge?') |
2089 exc.hint = _('do you want --merge?') |
2071 raise |
2090 raise |
2072 |
2091 |
2073 parents = wparents[0].parents() |
2092 parents = wparents[0].parents() |
2074 displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) |
2093 displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) |
2075 if len(parents) == 1: |
2094 if len(parents) == 1: |
2076 p = parents[0] |
2095 p = parents[0] |
2077 bm = bmactive(repo) |
2096 bm = bmactive(repo) |
2078 shouldmove = opts.get('move_bookmark') and bm is not None |
2097 shouldmove = opts.get('move_bookmark') and bm is not None |
2079 if dryrunopt: |
2098 if dryrunopt: |
2080 ui.write('hg update %s;\n' % p.rev()) |
2099 ui.write(('hg update %s;\n' % p.rev())) |
2081 if shouldmove: |
2100 if shouldmove: |
2082 ui.write('hg bookmark %s -r %s;\n' % (bm, p.rev())) |
2101 ui.write(('hg bookmark %s -r %s;\n' % (bm, p.rev()))) |
2083 else: |
2102 else: |
2084 ret = hg.update(repo, p.rev()) |
2103 ret = hg.update(repo, p.rev()) |
2085 if not ret: |
2104 if not ret: |
2086 wlock = repo.wlock() |
2105 wlock = repo.wlock() |
2087 try: |
2106 try: |
2103 @command('^next', |
2122 @command('^next', |
2104 [('B', 'move-bookmark', False, |
2123 [('B', 'move-bookmark', False, |
2105 _('move active bookmark after update')), |
2124 _('move active bookmark after update')), |
2106 ('', 'merge', False, _('bring uncommitted change along')), |
2125 ('', 'merge', False, _('bring uncommitted change along')), |
2107 ('', 'evolve', False, _('evolve the next changeset if necessary')), |
2126 ('', 'evolve', False, _('evolve the next changeset if necessary')), |
2108 ('n', 'dry-run', False, _('do not perform actions, just print what would be done'))], |
2127 ('n', 'dry-run', False, |
2109 '[OPTION]...') |
2128 _('do not perform actions, just print what would be done'))], |
|
2129 '[OPTION]...') |
2110 def cmdnext(ui, repo, **opts): |
2130 def cmdnext(ui, repo, **opts): |
2111 """update to next child |
2131 """update to next child |
2112 |
2132 |
2113 You can use the --evolve flag to get unstable children evolved on demand. |
2133 You can use the --evolve flag to get unstable children evolved on demand. |
2114 |
2134 |
2115 The summary line of the destination is displayed for clarity""" |
2135 The summary line of the destination is displayed for clarity""" |
2116 wkctx = repo[None] |
2136 wkctx = repo[None] |
2117 wparents = wkctx.parents() |
2137 wparents = wkctx.parents() |
2118 dryrunopt = opts['dry_run'] |
2138 dryrunopt = opts['dry_run'] |
2119 if len(wparents) != 1: |
2139 if len(wparents) != 1: |
2120 raise util.Abort('merge in progress') |
2140 raise error.Abort('merge in progress') |
2121 if not opts['merge']: |
2141 if not opts['merge']: |
2122 try: |
2142 try: |
2123 cmdutil.bailifchanged(repo) |
2143 cmdutil.bailifchanged(repo) |
2124 except error.Abort, exc: |
2144 except error.Abort as exc: |
2125 exc.hint = _('do you want --merge?') |
2145 exc.hint = _('do you want --merge?') |
2126 raise |
2146 raise |
2127 |
2147 |
2128 children = [ctx for ctx in wparents[0].children() if not ctx.obsolete()] |
2148 children = [ctx for ctx in wparents[0].children() if not ctx.obsolete()] |
2129 displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) |
2149 displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate}) |
2130 if len(children) == 1: |
2150 if len(children) == 1: |
2131 c = children[0] |
2151 c = children[0] |
2132 bm = bmactive(repo) |
2152 bm = bmactive(repo) |
2133 shouldmove = opts.get('move_bookmark') and bm is not None |
2153 shouldmove = opts.get('move_bookmark') and bm is not None |
2134 if dryrunopt: |
2154 if dryrunopt: |
2135 ui.write('hg update %s;\n' % c.rev()) |
2155 ui.write(('hg update %s;\n' % c.rev())) |
2136 if shouldmove: |
2156 if shouldmove: |
2137 ui.write('hg bookmark %s -r %s;\n' % (bm, c.rev())) |
2157 ui.write(('hg bookmark %s -r %s;\n' % (bm, c.rev()))) |
2138 else: |
2158 else: |
2139 ret = hg.update(repo, c.rev()) |
2159 ret = hg.update(repo, c.rev()) |
2140 if not ret: |
2160 if not ret: |
2141 wlock = repo.wlock() |
2161 wlock = repo.wlock() |
2142 try: |
2162 try: |
2240 [('n', 'new', [], _("successor changeset (DEPRECATED)")), |
2260 [('n', 'new', [], _("successor changeset (DEPRECATED)")), |
2241 ('s', 'succ', [], _("successor changeset")), |
2261 ('s', 'succ', [], _("successor changeset")), |
2242 ('r', 'rev', [], _("revisions to prune")), |
2262 ('r', 'rev', [], _("revisions to prune")), |
2243 ('k', 'keep', None, _("does not modify working copy during prune")), |
2263 ('k', 'keep', None, _("does not modify working copy during prune")), |
2244 ('', 'biject', False, _("do a 1-1 map between rev and successor ranges")), |
2264 ('', 'biject', False, _("do a 1-1 map between rev and successor ranges")), |
2245 ('', 'fold', False, _("record a fold (multiple precursors, one successors)")), |
2265 ('', 'fold', False, |
2246 ('', 'split', False, _("record a split (on precursor, multiple successors)")), |
2266 _("record a fold (multiple precursors, one successors)")), |
|
2267 ('', 'split', False, |
|
2268 _("record a split (on precursor, multiple successors)")), |
2247 ('B', 'bookmark', '', _("remove revs only reachable from given" |
2269 ('B', 'bookmark', '', _("remove revs only reachable from given" |
2248 " bookmark"))] + metadataopts, |
2270 " bookmark"))] + metadataopts, |
2249 _('[OPTION] [-r] REV...')) |
2271 _('[OPTION] [-r] REV...')) |
2250 # -U --noupdate option to prevent wc update and or bookmarks update ? |
2272 # -U --noupdate option to prevent wc update and or bookmarks update ? |
2251 def cmdprune(ui, repo, *revs, **opts): |
2273 def cmdprune(ui, repo, *revs, **opts): |
2302 revs.sort() |
2324 revs.sort() |
2303 for p in revs: |
2325 for p in revs: |
2304 cp = repo[p] |
2326 cp = repo[p] |
2305 if not cp.mutable(): |
2327 if not cp.mutable(): |
2306 # note: createmarkers() would have raised something anyway |
2328 # note: createmarkers() would have raised something anyway |
2307 raise util.Abort('cannot prune immutable changeset: %s' % cp, |
2329 raise error.Abort('cannot prune immutable changeset: %s' % cp, |
2308 hint='see "hg help phases" for details') |
2330 hint='see "hg help phases" for details') |
2309 precs.append(cp) |
2331 precs.append(cp) |
2310 if not precs: |
2332 if not precs: |
2311 raise util.Abort('nothing to prune') |
2333 raise error.Abort('nothing to prune') |
2312 |
2334 |
2313 if not obsolete.isenabled(repo, obsolete.allowunstableopt): |
2335 if not obsolete.isenabled(repo, obsolete.allowunstableopt): |
2314 if repo.revs("(%ld::) - %ld", revs, revs): |
2336 if repo.revs("(%ld::) - %ld", revs, revs): |
2315 raise util.Abort(_("cannot prune in the middle of a stack")) |
2337 raise error.Abort(_("cannot prune in the middle of a stack")) |
2316 |
2338 |
2317 # defines successors changesets |
2339 # defines successors changesets |
2318 sucs = scmutil.revrange(repo, succs) |
2340 sucs = scmutil.revrange(repo, succs) |
2319 sucs.sort() |
2341 sucs.sort() |
2320 sucs = tuple(repo[n] for n in sucs) |
2342 sucs = tuple(repo[n] for n in sucs) |
2321 if not biject and len(sucs) > 1 and len(precs) > 1: |
2343 if not biject and len(sucs) > 1 and len(precs) > 1: |
2322 msg = "Can't use multiple successors for multiple precursors" |
2344 msg = "Can't use multiple successors for multiple precursors" |
2323 raise util.Abort(msg) |
2345 raise error.Abort(msg) |
2324 elif biject and len(sucs) != len(precs): |
2346 elif biject and len(sucs) != len(precs): |
2325 msg = "Can't use %d successors for %d precursors" \ |
2347 msg = "Can't use %d successors for %d precursors" \ |
2326 % (len(sucs), len(precs)) |
2348 % (len(sucs), len(precs)) |
2327 raise util.Abort(msg) |
2349 raise error.Abort(msg) |
2328 elif (len(precs) == 1 and len(sucs) > 1) and not split: |
2350 elif (len(precs) == 1 and len(sucs) > 1) and not split: |
2329 msg = "please add --split if you want to do a split" |
2351 msg = "please add --split if you want to do a split" |
2330 raise util.Abort(msg) |
2352 raise error.Abort(msg) |
2331 elif len(sucs) == 1 and len(precs) > 1 and not fold: |
2353 elif len(sucs) == 1 and len(precs) > 1 and not fold: |
2332 msg = "please add --fold if you want to do a fold" |
2354 msg = "please add --fold if you want to do a fold" |
2333 raise util.Abort(msg) |
2355 raise error.Abort(msg) |
2334 elif biject: |
2356 elif biject: |
2335 relations = [(p, (s,)) for p, s in zip(precs, sucs)] |
2357 relations = [(p, (s,)) for p, s in zip(precs, sucs)] |
2336 else: |
2358 else: |
2337 relations = [(p, sucs) for p in precs] |
2359 relations = [(p, sucs) for p in precs] |
2338 |
2360 |
2579 try: |
2603 try: |
2580 wlock = repo.wlock() |
2604 wlock = repo.wlock() |
2581 lock = repo.lock() |
2605 lock = repo.lock() |
2582 wctx = repo[None] |
2606 wctx = repo[None] |
2583 if len(wctx.parents()) <= 0: |
2607 if len(wctx.parents()) <= 0: |
2584 raise util.Abort(_("cannot uncommit null changeset")) |
2608 raise error.Abort(_("cannot uncommit null changeset")) |
2585 if len(wctx.parents()) > 1: |
2609 if len(wctx.parents()) > 1: |
2586 raise util.Abort(_("cannot uncommit while merging")) |
2610 raise error.Abort(_("cannot uncommit while merging")) |
2587 old = repo['.'] |
2611 old = repo['.'] |
2588 if old.phase() == phases.public: |
2612 if old.phase() == phases.public: |
2589 raise util.Abort(_("cannot rewrite immutable changeset")) |
2613 raise error.Abort(_("cannot rewrite immutable changeset")) |
2590 if len(old.parents()) > 1: |
2614 if len(old.parents()) > 1: |
2591 raise util.Abort(_("cannot uncommit merge changeset")) |
2615 raise error.Abort(_("cannot uncommit merge changeset")) |
2592 oldphase = old.phase() |
2616 oldphase = old.phase() |
2593 |
2617 |
2594 |
2618 |
2595 rev = None |
2619 rev = None |
2596 if opts.get('rev'): |
2620 if opts.get('rev'): |
2597 rev = scmutil.revsingle(repo, opts.get('rev')) |
2621 rev = scmutil.revsingle(repo, opts.get('rev')) |
2598 ctx = repo[None] |
2622 ctx = repo[None] |
2599 if ctx.p1() == rev or ctx.p2() == rev: |
2623 if ctx.p1() == rev or ctx.p2() == rev: |
2600 raise util.Abort(_("cannot uncommit to parent changeset")) |
2624 raise error.Abort(_("cannot uncommit to parent changeset")) |
2601 |
2625 |
2602 onahead = old.rev() in repo.changelog.headrevs() |
2626 onahead = old.rev() in repo.changelog.headrevs() |
2603 disallowunstable = not obsolete.isenabled(repo, obsolete.allowunstableopt) |
2627 disallowunstable = not obsolete.isenabled(repo, |
|
2628 obsolete.allowunstableopt) |
2604 if disallowunstable and not onahead: |
2629 if disallowunstable and not onahead: |
2605 raise util.Abort(_("cannot uncommit in the middle of a stack")) |
2630 raise error.Abort(_("cannot uncommit in the middle of a stack")) |
2606 |
2631 |
2607 # Recommit the filtered changeset |
2632 # Recommit the filtered changeset |
2608 tr = repo.transaction('uncommit') |
2633 tr = repo.transaction('uncommit') |
2609 updatebookmarks = _bookmarksupdater(repo, old.node(), tr) |
2634 updatebookmarks = _bookmarksupdater(repo, old.node(), tr) |
2610 newid = None |
2635 newid = None |
2611 includeorexclude = opts.get('include') or opts.get('exclude') |
2636 includeorexclude = opts.get('include') or opts.get('exclude') |
2612 if (pats or includeorexclude or opts.get('all')): |
2637 if (pats or includeorexclude or opts.get('all')): |
2613 match = scmutil.match(old, pats, opts) |
2638 match = scmutil.match(old, pats, opts) |
2614 newid = _commitfiltered(repo, old, match, target=rev) |
2639 newid = _commitfiltered(repo, old, match, target=rev) |
2615 if newid is None: |
2640 if newid is None: |
2616 raise util.Abort(_('nothing to uncommit'), |
2641 raise error.Abort(_('nothing to uncommit'), |
2617 hint=_("use --all to uncommit all files")) |
2642 hint=_("use --all to uncommit all files")) |
2618 # Move local changes on filtered changeset |
2643 # Move local changes on filtered changeset |
2619 obsolete.createmarkers(repo, [(old, (repo[newid],))]) |
2644 obsolete.createmarkers(repo, [(old, (repo[newid],))]) |
2620 phases.retractboundary(repo, tr, oldphase, [newid]) |
2645 phases.retractboundary(repo, tr, oldphase, [newid]) |
2621 repo.dirstate.beginparentchange() |
2646 repo.dirstate.beginparentchange() |
2863 hg fold foo::@ --exact |
2889 hg fold foo::@ --exact |
2864 """ |
2890 """ |
2865 revs = list(revs) |
2891 revs = list(revs) |
2866 revs.extend(opts['rev']) |
2892 revs.extend(opts['rev']) |
2867 if not revs: |
2893 if not revs: |
2868 raise util.Abort(_('no revisions specified')) |
2894 raise error.Abort(_('no revisions specified')) |
2869 |
2895 |
2870 revs = scmutil.revrange(repo, revs) |
2896 revs = scmutil.revrange(repo, revs) |
2871 |
2897 |
2872 if not opts['exact']: |
2898 if not opts['exact']: |
2873 # Try to extend given revision starting from the working directory |
2899 # Try to extend given revision starting from the working directory |
2874 extrevs = repo.revs('(%ld::.) or (.::%ld)', revs, revs) |
2900 extrevs = repo.revs('(%ld::.) or (.::%ld)', revs, revs) |
2875 discardedrevs = [r for r in revs if r not in extrevs] |
2901 discardedrevs = [r for r in revs if r not in extrevs] |
2876 if discardedrevs: |
2902 if discardedrevs: |
2877 raise util.Abort(_("cannot fold non-linear revisions"), |
2903 raise error.Abort(_("cannot fold non-linear revisions"), |
2878 hint=_("given revisions are unrelated to parent " |
2904 hint=_("given revisions are unrelated to parent " |
2879 "of working directory")) |
2905 "of working directory")) |
2880 revs = extrevs |
2906 revs = extrevs |
2881 |
2907 |
2882 if len(revs) == 1: |
2908 if len(revs) == 1: |
2883 ui.write_err(_('single revision specified, nothing to fold\n')) |
2909 ui.write_err(_('single revision specified, nothing to fold\n')) |
2884 return 1 |
2910 return 1 |
2885 |
2911 |
2886 roots = repo.revs('roots(%ld)', revs) |
2912 roots = repo.revs('roots(%ld)', revs) |
2887 if len(roots) > 1: |
2913 if len(roots) > 1: |
2888 raise util.Abort(_("cannot fold non-linear revisions " |
2914 raise error.Abort(_("cannot fold non-linear revisions " |
2889 "(multiple roots given)")) |
2915 "(multiple roots given)")) |
2890 root = repo[roots.first()] |
2916 root = repo[roots.first()] |
2891 if root.phase() <= phases.public: |
2917 if root.phase() <= phases.public: |
2892 raise util.Abort(_("cannot fold public revisions")) |
2918 raise error.Abort(_("cannot fold public revisions")) |
2893 heads = repo.revs('heads(%ld)', revs) |
2919 heads = repo.revs('heads(%ld)', revs) |
2894 if len(heads) > 1: |
2920 if len(heads) > 1: |
2895 raise util.Abort(_("cannot fold non-linear revisions " |
2921 raise error.Abort(_("cannot fold non-linear revisions " |
2896 "(multiple heads given)")) |
2922 "(multiple heads given)")) |
2897 head = repo[heads.first()] |
2923 head = repo[heads.first()] |
2898 disallowunstable = not obsolete.isenabled(repo, obsolete.allowunstableopt) |
2924 disallowunstable = not obsolete.isenabled(repo, obsolete.allowunstableopt) |
2899 if disallowunstable: |
2925 if disallowunstable: |
2900 if repo.revs("(%ld::) - %ld", revs, revs): |
2926 if repo.revs("(%ld::) - %ld", revs, revs): |
2901 raise util.Abort(_("cannot fold chain not ending with a head "\ |
2927 raise error.Abort(_("cannot fold chain not ending with a head "\ |
2902 "or with branching")) |
2928 "or with branching")) |
2903 wlock = lock = None |
2929 wlock = lock = None |
2904 try: |
2930 try: |
2905 wlock = repo.wlock() |
2931 wlock = repo.wlock() |
2906 lock = repo.lock() |
2932 lock = repo.lock() |
3511 sha.update(m) |
3543 sha.update(m) |
3512 if entry: |
3544 if entry: |
3513 cache.append((ctx.node(), sha.digest())) |
3545 cache.append((ctx.node(), sha.digest())) |
3514 else: |
3546 else: |
3515 cache.append((ctx.node(), nullid)) |
3547 cache.append((ctx.node(), nullid)) |
3516 repo.ui.progress("preparing locally", i, total=len(unfi)) |
3548 repo.ui.progress(_("preparing locally"), i, total=len(unfi)) |
3517 repo.ui.progress("preparing locally", None) |
3549 repo.ui.progress(_("preparing locally"), None) |
3518 return cache |
3550 return cache |
3519 |
3551 |
3520 @command('debugobsrelsethashtree', |
3552 @command('debugobsrelsethashtree', |
3521 [('', 'v0', None, 'hash on marker format "0"'), |
3553 [('', 'v0', None, 'hash on marker format "0"'), |
3522 ('', 'v1', None, 'hash on marker format "1" (default)') |
3554 ('', 'v1', None, 'hash on marker format "1" (default)')] , _('')) |
3523 ,] , _('')) |
|
3524 def debugobsrelsethashtree(ui, repo, v0=False, v1=False): |
3555 def debugobsrelsethashtree(ui, repo, v0=False, v1=False): |
3525 """display Obsolete markers, Relevant Set, Hash Tree |
3556 """display Obsolete markers, Relevant Set, Hash Tree |
3526 changeset-node obsrelsethashtree-node |
3557 changeset-node obsrelsethashtree-node |
3527 |
3558 |
3528 It computed form the "orsht" of its parent and markers |
3559 It computed form the "orsht" of its parent and markers |
3529 relevant to the changeset itself.""" |
3560 relevant to the changeset itself.""" |
3530 if v0 and v1: |
3561 if v0 and v1: |
3531 raise util.Abort('cannot only specify one format') |
3562 raise error.Abort('cannot only specify one format') |
3532 elif v0: |
3563 elif v0: |
3533 treefunc = _obsrelsethashtreefm0 |
3564 treefunc = _obsrelsethashtreefm0 |
3534 else: |
3565 else: |
3535 treefunc = _obsrelsethashtreefm1 |
3566 treefunc = _obsrelsethashtreefm1 |
3536 |
3567 |