comparison mercurial/revset.py @ 29348:2188f170f5b6

revset: add new topographical sort Sort revisions in reverse revision order but grouped by topographical branches. Visualised as a graph, instead of: o 4 | | o 3 | | | o 2 | | o | 1 |/ o 0 revisions on a 'main' branch are emitted before 'side' branches: o 4 | o 1 | | o 3 | | | o 2 |/ o 0 where what constitutes a 'main' branch is configurable, so the sort could also result in: o 3 | o 2 | | o 4 | | | o 1 |/ o 0 This sort was already available as an experimental option in the graphmod module, from which it is now removed. This sort is best used with hg log -G: $ hg log -G "sort(all(), topo)"
author Martijn Pieters <mjpieters@fb.com>
date Mon, 13 Jun 2016 18:20:00 +0100
parents 98535ad46fc0
children ec75d77df9d7
comparison
equal deleted inserted replaced
29347:98535ad46fc0 29348:2188f170f5b6
1841 'user': lambda c: c.user(), 1841 'user': lambda c: c.user(),
1842 'author': lambda c: c.user(), 1842 'author': lambda c: c.user(),
1843 'date': lambda c: c.date()[0], 1843 'date': lambda c: c.date()[0],
1844 } 1844 }
1845 1845
1846 @predicate('sort(set[, [-]key...])', safe=True) 1846 @predicate('sort(set[, [-]key... [, ...]])', safe=True)
1847 def sort(repo, subset, x): 1847 def sort(repo, subset, x):
1848 """Sort set by keys. The default sort order is ascending, specify a key 1848 """Sort set by keys. The default sort order is ascending, specify a key
1849 as ``-key`` to sort in descending order. 1849 as ``-key`` to sort in descending order.
1850 1850
1851 The keys can be: 1851 The keys can be:
1853 - ``rev`` for the revision number, 1853 - ``rev`` for the revision number,
1854 - ``branch`` for the branch name, 1854 - ``branch`` for the branch name,
1855 - ``desc`` for the commit message (description), 1855 - ``desc`` for the commit message (description),
1856 - ``user`` for user name (``author`` can be used as an alias), 1856 - ``user`` for user name (``author`` can be used as an alias),
1857 - ``date`` for the commit date 1857 - ``date`` for the commit date
1858 """ 1858 - ``topo`` for a reverse topographical sort
1859 args = getargsdict(x, 'sort', 'set keys') 1859
1860 The ``topo`` sort order cannot be combined with other sort keys. This sort
1861 takes one optional argument, ``topo.firstbranch``, which takes a revset that
1862 specifies what topographical branches to prioritize in the sort.
1863
1864 """
1865 args = getargsdict(x, 'sort', 'set keys topo.firstbranch')
1860 if 'set' not in args: 1866 if 'set' not in args:
1861 # i18n: "sort" is a keyword 1867 # i18n: "sort" is a keyword
1862 raise error.ParseError(_('sort requires one or two arguments')) 1868 raise error.ParseError(_('sort requires one or two arguments'))
1863 keys = "rev" 1869 keys = "rev"
1864 if 'keys' in args: 1870 if 'keys' in args:
1866 keys = getstring(args['keys'], _("sort spec must be a string")) 1872 keys = getstring(args['keys'], _("sort spec must be a string"))
1867 1873
1868 s = args['set'] 1874 s = args['set']
1869 keys = keys.split() 1875 keys = keys.split()
1870 revs = getset(repo, subset, s) 1876 revs = getset(repo, subset, s)
1877
1878 if len(keys) > 1 and any(k.lstrip('-') == 'topo' for k in keys):
1879 # i18n: "topo" is a keyword
1880 raise error.ParseError(_(
1881 'topo sort order cannot be combined with other sort keys'))
1882
1883 firstbranch = ()
1884 if 'topo.firstbranch' in args:
1885 if any(k.lstrip('-') == 'topo' for k in keys):
1886 firstbranch = getset(repo, subset, args['topo.firstbranch'])
1887 else:
1888 # i18n: "topo" and "topo.firstbranch" are keywords
1889 raise error.ParseError(_(
1890 'topo.firstbranch can only be used when using the topo sort '
1891 'key'))
1892
1871 if keys == ["rev"]: 1893 if keys == ["rev"]:
1872 revs.sort() 1894 revs.sort()
1873 return revs 1895 return revs
1874 elif keys == ["-rev"]: 1896 elif keys == ["-rev"]:
1875 revs.sort(reverse=True) 1897 revs.sort(reverse=True)
1876 return revs 1898 return revs
1899 elif keys[0] in ("topo", "-topo"):
1900 revs = baseset(_toposort(revs, repo.changelog.parentrevs, firstbranch),
1901 istopo=True)
1902 if keys[0][0] == '-':
1903 revs.reverse()
1904 return revs
1905
1877 # sort() is guaranteed to be stable 1906 # sort() is guaranteed to be stable
1878 ctxs = [repo[r] for r in revs] 1907 ctxs = [repo[r] for r in revs]
1879 for k in reversed(keys): 1908 for k in reversed(keys):
1880 fk = k 1909 fk = k
1881 reverse = (k[0] == '-') 1910 reverse = (k[0] == '-')
1885 ctxs.sort(key=_sortkeyfuncs[k], reverse=reverse) 1914 ctxs.sort(key=_sortkeyfuncs[k], reverse=reverse)
1886 except KeyError: 1915 except KeyError:
1887 raise error.ParseError(_("unknown sort key %r") % fk) 1916 raise error.ParseError(_("unknown sort key %r") % fk)
1888 return baseset([c.rev() for c in ctxs]) 1917 return baseset([c.rev() for c in ctxs])
1889 1918
1890 def groupbranchiter(revs, parentsfunc, firstbranch=()): 1919 def _toposort(revs, parentsfunc, firstbranch=()):
1891 """Yield revisions from heads to roots one (topo) branch at a time. 1920 """Yield revisions from heads to roots one (topo) branch at a time.
1892 1921
1893 This function aims to be used by a graph generator that wishes to minimize 1922 This function aims to be used by a graph generator that wishes to minimize
1894 the number of parallel branches and their interleaving. 1923 the number of parallel branches and their interleaving.
1895 1924