Commit Graph

800 Commits

Author SHA1 Message Date
Gábor Stefanik
71039079d7 revset: support "follow(renamed.py, e22f4f3f06c3)" (issue5334)
v2: fixes from review
2016-08-18 17:25:10 +02:00
Augie Fackler
cb268cbd2f merge with stable 2016-08-15 12:26:02 -04:00
Yuya Nishihara
320973b5ef revset: fix keyword arguments to go through optimization process
Before, a keyvalue node was processed by the last catch-all condition of
_optimize(). Therefore, topo.firstbranch=expr would bypass tree rewriting
and would crash if an expr wasn't trivial.
2016-08-07 14:58:49 +09:00
FUJIWARA Katsunori
5f2b407a05 revset: refactor to make xgettext put i18n comments into hg.pot file
xgettext expects both "_()" and (a part of) text to be placed at just
next line of "i18n:" comment.
2016-08-01 06:08:26 +09:00
Yuya Nishihara
1cc6421086 revset: also parse x^: as (x^):
Given x^:y is (x^):y, this seems sensible.
2016-08-06 20:37:48 +09:00
Yuya Nishihara
992f4bdde9 revset: resolve ambiguity of x^:y before alias expansion
This is purely a parsing problem, which should be resolved before alias
expansion.
2016-08-06 20:21:00 +09:00
Yuya Nishihara
ba3291048d revset: check invalid function syntax "func-name"() explicitly
Before the error was caught at func() as an unknown identifier, and the
optimizer failed to detect the syntax error. This patch introduces getsymbol()
helper to ensure that a string is not allowed as a function name.
2016-06-27 20:44:14 +09:00
Yuya Nishihara
7323118189 revset: get rid of redundant error checking from match()
Actually there was no additional error checking. It should be caught by
"not all(specs)".
2016-06-26 17:16:57 +09:00
Gregory Szorc
aa5486b692 revset: implement match() in terms of matchany()
match() is the special case of a single element list being passed
to matchany() with the additional error checking that the revset
spec is defined. Change the implementation to remove the redundant
code and have match() call matchany().
2016-06-25 19:10:46 -07:00
Martin von Zweigbergk
59e258644a revset: make head() honor order of subset
The ordering of 'x & head()' was broken in 329d82866742 (revset:
improve head revset performance, 2014-03-13). Presumably due to other
optimizations since then, undoing that change to fix the order does
not slow down the simple case of "hg log -r 'head()'" mentioned in
that commit. I see a small slowdown from ~0.16s to about ~0.19s with
'not 0 & head()', but I'd say it's worth it for the correct output.
2016-06-23 12:37:09 -07:00
Martin von Zweigbergk
f44cccc475 revsets: use itervalues() where only values are needed
I don't think there will be a noticeable speedup, but it removes an
unused variable.
2016-06-23 13:08:10 -07:00
Martin von Zweigbergk
792eb4d1ec revsets: passing a set to baseset() is not wrong
Since 303be3afebae (revset: force ascending order for baseset
initialized from a set, 2016-04-04), it is safe to pass a revset to a
baseset.
2016-06-23 12:39:05 -07:00
liscju
c7ec9d159e i18n: translate abort messages
I found a few places where message given to abort is
not translated, I don't find any reason to not translate
them.
2016-06-14 11:53:55 +02:00
Yuya Nishihara
1c12bcd4ad revset: extract function that validates sort() arguments
This function will be used in _optimize() to get rid of noop sort() call while
validating its arguments.
2016-06-11 10:17:49 +09:00
Yuya Nishihara
2ddc948200 revset: build dict of extra sort options before evaluating set
Prepares for extracting a function that only validates sort options.
2016-06-15 21:26:45 +09:00
Yuya Nishihara
1ee4615445 revset: build list of (key, reverse) pairs before sorting
Prepares for extracting a function that only validates sort options.
2016-06-11 10:15:40 +09:00
Yuya Nishihara
4659949bd1 revset: fix crash on empty sort key
Make it noop as before ddf6bfe09ab2. We could change it to an error, but
allowing empty key makes some sense for scripting that builds a key string
programmatically.
2016-06-15 20:37:24 +09:00
Martijn Pieters
6cc53d84c9 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)"
2016-06-13 18:20:00 +01:00
Martijn Pieters
57bf8caf56 revset: move groupbranchiter over from graphmod
This move is to prepare the adaptation of this function into a toposort
predicate.
2016-06-13 18:20:00 +01:00
Martijn Pieters
ffccd3fc81 revset: record if a set is in topographical order
A later revision adds actual topographical sorting. Recording if a set is in
this order allows hg log -G to avoid re-sorting the revset.
2016-06-14 11:05:36 +01:00
Kostia Balytskyi
5501c91461 revset: make filteredset.__nonzero__ respect the order of the filteredset
This fix allows __nonzero__ to respect the direction of iteration of the
whole filteredset. Here's the case when it matters. Imagine that we have a
very large repository and we want to execute a command like:

    $ hg log --rev '(tip:0) and user(ikostia)' --limit 1

(we want to get the latest commit by me).

Mercurial will evaluate a filteredset lazy data structure, an
instance of the filteredset class, which will know that it has to iterate
in a descending order (isdescending() will return True if called). This
means that when some code iterates over the instance of this filteredset,
the 'and user(ikostia)' condition will be first checked on the latest
revision, then on the second latest and so on, allowing Mercurial to
print matches as it founds them. However, cmdutil.getgraphlogrevs
contains the following code:

    revs = _logrevs(repo, opts)
    if not revs:
        return revset.baseset(), None, None

The "not revs" expression is evaluated by calling filteredset.__nonzero__,
which in its current implementation will try to iterate the filteredset
in ascending order until it finds a revision that matches the 'and user(..'
condition. If the condition is only true on late revisions, a lot of
useless iterations will be done. These iterations could be avoided if
__nonzero__ followed the order of the filteredset, which in my opinion
is a sensible thing to do here.

The problem gets even worse when instead of 'user(ikostia)' some more
expensive check is performed, like grepping the commit diff.


I tested this fix on a very large repo where tip is my commit and my very
first commit comes fairly late in the revision history. Results of timing
of the above command on that very large repo.

-with my fix:
real    0m1.795s
user    0m1.657s
sys     0m0.135s

-without my fix:
real    1m29.245s
user    1m28.223s
sys     0m0.929s

I understand that this is a very specific kind of problem that presents
itself very rarely, only on very big repositories and with expensive
checks and so on. But I don't see any disadvantages to this kind of fix
either.
2016-06-02 22:39:01 +01:00
Yuya Nishihara
e2af538ed7 revset: define table of sort() key functions
This should be more readable than big "if" branch.
2016-05-14 19:52:00 +09:00
Yuya Nishihara
9079f0d3ff revset: factor out reverse flag of sort() key
Prepares for making a table of sort keys. This assumes 'k' has at least one
character, which should be guaranteed by keys.split().
2016-05-14 19:46:18 +09:00
Martijn Pieters
4501d84df3 revset: use getargsdict for sort()
This makes it possible to use keyword arguments to specify per-sort options.
For example, a hypothetical 'first' option for the user sort could sort certain
users first with:

    sort(all(), user, user.first=mpm@selenic.com)
2016-05-23 14:09:50 -07:00
timeless
a1cb3173a2 py3: convert to next() function
next(..) was introduced in py2.6 and .next() is not available in py3

https://docs.python.org/2/library/functions.html#next
2016-05-16 21:30:53 +00:00
timeless
db06992202 revset: rename variable to avoid shadowing with builtin next() function
https://docs.python.org/2/library/functions.html#next
2016-05-16 21:30:32 +00:00
Pierre-Yves David
efaf172347 devel: fix a typo in a deprecation warning
Credit goes to Sean Farley for spotting it.
2016-05-11 09:34:59 +02:00
Pierre-Yves David
4bd2f39b1d devel: officially deprecate old style revset
When we introduce the develwarning, we did not had an official deprecation API
and infrastructure. We can now officially deprecate the old way with a version
deadline.
2016-05-11 09:31:47 +02:00
Yuya Nishihara
2644883398 revset: make dagrange preserve order of input set
Unlike range, dagrange has no inverted range (such as '10:0'). So there should
be no practical reason to keep dagrange as a function that forces its own
ordering.

No performance regression is spotted in contrib/base-revsets.txt.
2016-05-03 12:36:44 +09:00
Yuya Nishihara
d1b0332b16 revset: factor out public optimize() function from recursion
New optimize() hides internal arguments and return values. This makes it easy
to add more parameters and return values to _optimize().
2016-05-02 12:09:00 +09:00
Yuya Nishihara
f18ad29e0a revset: introduce temporary variables in optimize() where they look better 2016-05-02 12:47:09 +09:00
Yuya Nishihara
3a2b799928 revset: construct arguments of only() against matched tree
Since _isonly() knows the structure of 'revs' and 'bases', it should be
slightly easier to understand than destructuring 'ta' and 'tb'.
2016-05-02 11:50:48 +09:00
Yuya Nishihara
dff8edf1fe revset: unnest isonly() closure from optimize()
There were no variables to be captured.
2016-05-02 11:27:26 +09:00
Pierre-Yves David
5d9e7dcea2 devel: use the new 'config' argument for the revset develwarn 2016-05-08 10:43:41 +02:00
Yuya Nishihara
96d6f9fd5f revset: define _parsealias() in _aliasrules class
It's short. It doesn't make sense to define _parsealias() outside of the
class.
2016-04-17 13:06:44 +09:00
Yuya Nishihara
74d711b196 revset: factor out common parsing function 2016-04-17 13:03:23 +09:00
Yuya Nishihara
2838ac3dce revset: inline _tokenizealias() into _parsealias()
This helps factoring out common part between _parsealias() and parse().
2016-04-17 12:57:27 +09:00
Yuya Nishihara
e316e79cfe parser: remove unused binding parameter from suffix action
Because a suffix action never takes subsequent tokens, it should have
no binding strength nor closing character. I've tried if this value could
be used to resolve infix/suffix ambiguity of x^:y, but it appears not. So
I decided to resend this patch.
2015-07-05 21:11:19 +09:00
Yuya Nishihara
5ed7576a38 revset: unindent "if True" block in sort()
It was there to make the previous patch readable.
2016-04-23 16:11:05 +09:00
Yuya Nishihara
37d980f070 revset: make sort() do dumb multi-pass sorting for multiple keys (issue5218)
Our invert() function was too clever to not take length into account. I could
fix the problem by appending '\xff' as a terminator (opposite to '\0'), but
it turned out to be slower than simple multi-pass sorting.

New implementation is pretty straightforward, which just calls sort() from the
last key. We can do that since Python sort() is guaranteed to be stable. It
doesn't sound nice to call sort() multiple times, but actually it is faster.
That's probably because we have fewer Python codes in hot loop, and can avoid
heavy string and list manipulation.

  revset #0: sort(0:10000, 'branch')
  0) 0.412753
  1) 0.393254

  revset #1: sort(0:10000, '-branch')
  0) 0.455377
  1) 0.389191  85%

  revset #2: sort(0:10000, 'date')
  0) 0.408082
  1) 0.376332  92%

  revset #3: sort(0:10000, '-date')
  0) 0.406910
  1) 0.380498  93%

  revset #4: sort(0:10000, 'desc branch user date rev')
  0) 0.542996
  1) 0.486397  89%

  revset #5: sort(0:10000, '-desc -branch -user -date -rev')
  0) 0.965032
  1) 0.518426  53%
2016-04-23 16:09:30 +09:00
Yuya Nishihara
85d1a67355 parser: factor out _trygetfunc() that extracts function name and arguments
This provides a customization point for templater. In templater, there are
two ways to call a unary function: func(x) and x|func. They are processed
differently in templater due to historical reasons, but they should be
handled in the same way while expanding aliases. In short, x|func should be
processed as syntactic sugar for func(x).

_funcnode and _getlist() are replaced by _trygetfunc().
2016-03-29 17:27:34 +09:00
Yuya Nishihara
4d9561138b revset: rename findaliases() to expandaliases()
This function returns a full tree of alias expansion applied, which sounds
different from what "findaliases" would do.
2016-02-29 22:58:15 +09:00
Yuya Nishihara
45e9c21bc0 parser: move functions that process alias expansion to rule-set class
They will be commonly used by revset and templater. It isn't easy to understand
how _expand() works, so I'll add comments by a follow-up patch.

The local variable 'alias' is renamed to 'a' to avoid shadowing the global
'alias' class.
2016-02-29 22:15:44 +09:00
Yuya Nishihara
5da75dff02 revset: unindent codes in _getalias() function
We generally do return early if tree isn't a tuple.
2016-02-29 22:10:48 +09:00
Yuya Nishihara
a98783fa06 parser: extract helper that creates a dict of aliases
This will be common between revset and templater.

The local variable 'alias' is renamed to 'a' to avoid shadowing the global
'alias' class.
2016-02-29 19:24:15 +09:00
Yuya Nishihara
53c5cbd213 parser: construct alias object by rule-set class
It was odd that the revsetalias did the whole parsing stuff in __init__().
Instead, this patch adds a factory function to the aliasrules class, and
makes the alias (= revsetalias) class a plain-old value object.
2016-02-29 18:33:30 +09:00
Yuya Nishihara
2e16bca7bf parser: unify parser function of alias declaration and definition
We no longer have to keep them separately.
2016-03-29 00:08:25 +09:00
Yuya Nishihara
06651e61a2 revset: unify function that parses alias declaration and definition
We no longer need separate parsers. Only difference between _parsealiasdecl()
and _parsealiasdefn() is whether or not to flatten 'or' tree. Since alias
declaration should have no 'or' operator, there was no practical difference.
2016-03-29 00:05:14 +09:00
Yuya Nishihara
5392dbd7d3 parser: move alias definition parser to common rule-set class
The original _parsealiasdefn() function is split into common _builddefn()
and revset-specific _parsealiasdefn(). revset._relabelaliasargs() is removed
as it is no longer used.

The doctests are ported by using the dummy parse().
2016-02-29 18:10:07 +09:00
Yuya Nishihara
188dee35c2 parser: move _relabelaliasargs() to common rule-set class
This has no doctest because it will be covered by _builddefn() introduced
by the next patch.

revset._relabelaliasargs() will be removed soon.
2016-02-29 18:00:51 +09:00