Mercurial > public > mercurial-scm > hg
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 |