Commit Graph

712 Commits

Author SHA1 Message Date
Pierre-Yves David
d810f109b3 lazyset: drop now useless ascending/descending definition 2014-10-02 18:52:09 -05:00
Pierre-Yves David
4be4f3fe52 lazyset: inherit the fastasc and fastdesc method from subset
When the filtered subset has such methods, we can use them. It is implemented
as properties to be able to quickly return None if no corresponding fastasc exists
on the subset.
2014-09-30 23:36:57 -05:00
Pierre-Yves David
b0f4537a2a lazyset: split the iteration logic from the condition filtering logic
So that the filter can be reused by `fastasc` or `fastdesc`.
2014-10-02 18:25:37 -05:00
Pierre-Yves David
5310fa5e65 spanset: do a single range check in __contains__
Now that `start <= end` is always true, we can simplify this function.
2014-10-02 17:53:55 -05:00
Pierre-Yves David
9d76d87327 spanset: enforce the order lazily to gain fastasc and fastdesc methods
Instead of having the direction of iteration enforced through the ordering of
`start` and `end` attributes of spanset, we encode the iteration direction in
an explicit attribute and always store start < end.  The logic for sort and
reverse has to be updated. The __iter__ is now based on the newly introduced
`fastasc` and `fastdesc` methods.

This will allow other code simplifications in the future.
2014-10-02 18:02:17 -05:00
Pierre-Yves David
82a1d861c5 abstractsmartset: document the fastasc and fastdesc attributes/methods
See the in-line documentation for details. (This is the beginning of a massive
overhaul of revset).
2014-09-30 22:26:34 -05:00
Pierre-Yves David
177faece69 spanset: remove ascending/descending implementation
We can rely on their implementation in abstractsmartset.
2014-10-02 18:35:56 -05:00
Pierre-Yves David
2b0dd7c610 baseset: remove ascending/descending redefinition
We can rely on the abstractsmartset implementation.
2014-10-02 18:35:00 -05:00
Pierre-Yves David
765584f8b2 abstractsmartset: default implementation for ascending and descending
These two methods are actually silly aliases for `sort()` and
`sort(reverse=True)`. So we get that aliasing at the abstractsmartset level. We
will slowly phase out all the custom implementations and eventually remove any
mentions of it from the code.
2014-10-02 18:34:18 -05:00
Pierre-Yves David
1b61d96256 revert: bring back usage of subset & ps in parents
Changeset 1440ec8e33c0 switched the order of the operand of the "&" computation
to work around an issue from repo-wide spanset. The need for a workaround has been
alleviated by the introduction of `fullreposet`. So we restore it to normal.

The benchmark shows no significant changes as expected.

We also revert the bogus test change introduced by 1440ec8e33c0. The order is
actually important.
2014-09-17 04:55:55 -07:00
Pierre-Yves David
166e755bd8 revset: introduce an abstractsmartset class
This class documents all methods required by a smartset. This makes it easier
for people to respect the API and ensure we fail loudly when something does
not. It will later also contain common default implementations for multiple
methods, making it easier to have smartset classes with minimal work.
2014-10-01 15:14:36 -05:00
Pierre-Yves David
63c5d3af3b revset: add a __nonzero__ to baseset
We are about to add a base class for `baseset` with an abstract `__nonzero__`
method. So we need this method to be explicitly defined to avoid issues. The
built-in list object apparently does not have a `__nonzero__` and relies on
`__len__` for this purpose?
2014-10-01 15:03:16 -05:00
Pierre-Yves David
a44ac390ee revset: drop isinstance(baseset) in spanset.__sub__
As baseset now has a fast __contains___ operator, this `baseset.set()` dance is no
longer needed. No regressions are visible in the benchmark.
2014-10-01 15:50:54 -05:00
Pierre-Yves David
43c1a7c7b7 revset: drop isinstance(baseset) in spanset.__and__
As baseset now has a fast __contains___ operator, this `baseset.set()` dance is no
longer needed. No regressions are visible in the benchmark.
2014-10-01 15:50:40 -05:00
Pierre-Yves David
3c21cdaa54 revset: drop isinstance(baseset) from baseset.__and__
As baseset now has a fast __contains___ operator, this `baseset.set()` dance is
no longer needed. No regressions are visible in the benchmark.
2014-09-30 23:09:59 -05:00
Pierre-Yves David
3a3ec48d95 revset: use direct access to __contains__ in spanset.__sub__
Using `x.__contains__(r)` instead of `r in x` does not matter for built-in type
(set) but have a positive impact for all other classes. This will let us drop
some usage of baseset.set() in future patches. This also probably improves some
performance.
2014-10-01 15:53:42 -05:00
Pierre-Yves David
d93cff0448 revset: use a single return statement in matcher function
This makes it easy to insert post processing and debug code on the returned
value.
2014-09-30 12:39:21 -05:00
Pierre-Yves David
2a8200e655 revset: rely on built in iterator when possible in _generatorset.__iter__
Doing manual iteration is expensible. We rely on built in list iteration
whenever possible. The other case has to become a closure we cannot have a both
yield and return in the same function.
2014-04-30 16:56:23 -07:00
Pierre-Yves David
c6262025ca revset: prefetch an attribute in _generatorset.__iter__
Python's attribute lookup are expensible, lets do less of them.

This gives us a 7% speedup on this revset iteration (from 0.063403 to 0.059032)
2014-09-18 15:52:45 -07:00
Pierre-Yves David
a7bd255d53 revset: use subset & in bare p2()
This takes advantage of the `fullreposet` smartness with a nice
speedup. It's a similar speedup to `p1()` when a merge is in progress
(the non merge case is already lightning fast anyway.)
2014-09-17 11:00:03 -07:00
Pierre-Yves David
85eb5c83a9 revset: use subset & in bare p1()
This takes advantage of the `fullreposet` smartness and yields a nice
speedup.

revset #0: p1()
0) wall 0.003256 comb 0.010000 user 0.010000 sys 0.000000 (best of 527)
1) wall 0.000066 comb 0.000000 user 0.000000 sys 0.000000 (best of 23224)
2014-09-17 10:59:52 -07:00
Pierre-Yves David
8cb4d64b32 revset: use subset & in rev
This takes advantage of the `fullreposet` smartness and yields a nice
speedup.

revset #0: rev(25)
0) wall 0.005480 comb 0.000000 user 0.000000 sys 0.000000 (best of 305)
1) wall 0.000052 comb 0.000000 user 0.000000 sys 0.000000 (best of 21891)
2014-09-17 11:00:09 -07:00
Pierre-Yves David
375f152fed revset: use subset & in origin
This takes advantage of the `fullreposet` smartness.

revset #0: origin(tip)
0) wall 0.005353 comb 0.000000 user 0.000000 sys 0.000000 (best of 354)
1) wall 0.003080 comb 0.000000 user 0.000000 sys 0.000000 (best of 446)
2014-09-17 19:52:34 -07:00
Pierre-Yves David
fe68969345 revset: use subset & in follow
This takes advantage of the `fullreposet` smartness.


revset #0: follow(COPYING)
0) wall 0.002446 comb 0.000000 user 0.000000 sys 0.000000 (best of 735)
1) wall 0.000331 comb 0.000000 user 0.000000 sys 0.000000 (best of 5672)
2014-09-17 10:59:16 -07:00
Pierre-Yves David
a3297e9a12 revset: use subset & in filelog
This takes advantage of the `fullreposet` smartness.

revset #0: file(COPYING)
0) wall 3.179066 comb 3.180000 user 3.140000 sys 0.040000 (best of 3)
1) wall 2.723699 comb 2.730000 user 2.690000 sys 0.040000 (best of 4)
2014-09-17 10:58:50 -07:00
Pierre-Yves David
244ffda42c revset: use subset & in divergent
This takes advantage of the `fullreposet` smartness.

revset #0: divergent()
0) wall 0.002047 comb 0.000000 user 0.000000 sys 0.000000 (best of 813)
1) wall 0.000052 comb 0.000000 user 0.000000 sys 0.000000 (best of 22757)
2014-09-17 10:58:39 -07:00
Pierre-Yves David
4cc5660e43 revset: use subset & in bisect
This takes advantage of the `fullreposet` smartness.

revset #0: bisect(range)
0) wall 0.014007 comb 0.010000 user 0.010000 sys 0.000000 (best of 115)
1) wall 0.005556 comb 0.010000 user 0.010000 sys 0.000000 (best of 235)
2014-09-17 10:57:57 -07:00
Pierre-Yves David
35c1eba9e6 revset: use subset & in ancestorspec
This takes advantage of the `fullreposet` smartness.


revset #0: tip~25
0) wall 0.004800 comb 0.010000 user 0.010000 sys 0.000000 (best of 259)
1) wall 0.002475 comb 0.000000 user 0.000000 sys 0.000000 (best of 717)
2014-09-17 10:57:47 -07:00
Pierre-Yves David
25b1e1b399 revset: use subset & in bookmark
Speedup, Weeeeeee!

revset #0: bookmark()
0) wall 0.002240 comb 0.000000 user 0.000000 sys 0.000000 (best of 571)
1) wall 0.000132 comb 0.000000 user 0.000000 sys 0.000000 (best of 14059)
2014-09-17 19:57:09 -07:00
Pierre-Yves David
cefa7eaabc revset: use subset & in outgoing
This should give us the same benefit as elsewhere. Result is simpler (and
"faster").

Outgoing is dominated by the discovery so no benchmark is provided.
2014-09-17 10:59:40 -07:00
Pierre-Yves David
490d3a84ce revset: avoid in loop lookup in _generatorset._consumegen
Python lookups are slow, so do all lookup outside of the for loop.

This provide a small but still significant speedup:

revset #0: 0::
0) wall 0.063258 comb 0.060000 user 0.060000 sys 0.000000 (best of 100)
1) wall 0.057776 comb 0.050000 user 0.050000 sys 0.000000 (best of 100)
2014-04-30 16:56:48 -07:00
Pierre-Yves David
ae357027fd revset: reduce dict lookup in lazyset.__contains__
Avoid an extra dict lookup when we have to compute the value. No
visible performance impact but this shaves the yak a few extra
nanometers.
2014-04-25 14:51:24 -07:00
Pierre-Yves David
e291b5bdba revset: do less lookup during spanset.__contains__
Attribute lookup is slow in python. So this version is going to be a bit
faster. This does not have a visible impact since the rest of the stack is much
slower but this shaves the yak a few extra nanometers.

Moreover the new version is more readable so it worth doing this change for code
quality purpose.

This optimisation was approved by a core python dev.
2014-04-25 17:53:58 -07:00
Pierre-Yves David
477ee214de revset: fast implementation for fullreposet.__and__
"And" operation with something that contains the whole repo should be super
cheap. Check method docstring for details.

This provide massive boost to simple revset that use `subset & xxx`

revset #0: p1(20000)
0) wall 0.002447 comb 0.010000 user 0.010000 sys 0.000000 (best of 767)
1) wall 0.000529 comb 0.000000 user 0.000000 sys 0.000000 (best of 3947)

revset #1: p2(10000)
0) wall 0.002464 comb 0.000000 user 0.000000 sys 0.000000 (best of 913)
1) wall 0.000530 comb 0.000000 user 0.000000 sys 0.000000 (best of 4226)

No other regression spotted.

More performance improvements are expected in the future as more
revset predicate are converted to use `subset & xxx`

The relaxed way `fullreposet` handles "&" operation may cause some trouble for
people comparing smartset from different filter levels. I'm not sure such people
exist and we can improve that aspect in later patches.
2014-09-24 20:11:36 -07:00
Pierre-Yves David
acb7d8cae1 revset: turn spanset into a factory function
We rename the `spanset` class to `_spanset`. `spanset` is now a function that
builds either a `fullreposet` or a `_spanset` according to the argument passed.

At some point, we may force people to explicitly use the `fullreposet`
constructor, but the current approach makes it easier to ensure we use the new
class whenever possible and focus on the benefits of this class.
2014-09-18 13:04:02 -07:00
Pierre-Yves David
8febe1e995 revert: add a fullreposet class
Every revset evaluation starts from `subset = spanset(repo)` and a lot of
revset predicates build a `spansetrepo` for their internal needs.

`spanset` is a generic class that can handle any situation. As a result a lot
of operation between spanset result in an `orderedlazyset`, a safe object but
suboptimal in may situation.

So we introduce a `fullreposet` class where some of the operation will be
overwritten to produce more interesting results.
2014-04-29 19:06:15 -07:00
Matt Mackall
0e7a6163da merge with stable 2014-09-27 13:18:10 -05:00
Pierre-Yves David
537742ab10 revset: remove nullrev from the bookmark computation
Same as for other revset we sanitize the content of the set to be able to rely
on it more.
2014-09-17 19:56:59 -07:00
Pierre-Yves David
a06107e4f9 revset: unify code flow in bookmark
We refactor the code of the bookmark revset to have a single return. This will
allow us to sanitize the content of the set.
2014-09-17 10:58:25 -07:00
Pierre-Yves David
9cdb9e5a5d revset: remove invalid value in the origin set
Same as the parents related revsets, origin had some invalid value in the
computed set. We remove them.
2014-09-17 10:59:30 -07:00
Pierre-Yves David
5005f69963 revset: remove nullrev from set computed in parents()
The old code relied on the subset contents to get rid of invalid values. We would
like to be able to rely more on the computation in parents() so we filter out
the invalid value.
2014-09-17 19:49:26 -07:00
Pierre-Yves David
1601426b0b revset: refactor parents() into a single return point
Both paths are doing similar thing in the end. We refactor the function so that
the `ps` set is commonly used at the end.

This will end excluding `nullrev` from this set in a future patch
2014-09-17 19:44:03 -07:00
Pierre-Yves David
3e189cc195 revset: remove nullrev from set computed in p1() and p2()
The old code relied on the subset contents to get rid of invalid values. We would
like to be able to rely more on the computation in p1() and p2() so we filter out
the invalid value
2014-09-17 04:40:30 -07:00
Pierre-Yves David
d0e7545de8 revset: add an optimised baseset.__contains__ (issue4371)
The baseset class is based on a python list. This means that base.__contains__
was absolutely as crappy as list.__contains__. We now rely on __contains__ from
the underlying set.

This will avoid having to explicitly convert the baseset to a set (using
baseset.set()) whenever one want fast membership test.

Apparently there is already code that forgot to do such conversions since we
observe a massive speedup in some test.

revset #25: roots((0::) - (0::tip))
0) wall 2.079454 comb 2.080000 user 2.080000 sys 0.000000 (best of 5)
1) wall 0.132970 comb 0.130000 user 0.130000 sys 0.000000 (best of 65)

No regression is observed in benchmarks.

This change improve the issue4371 back to acceptable situation (but are still
slower than manual substraction)
2014-09-16 23:59:29 -07:00
Pierre-Yves David
27c652135f revset: document the choice made in __generatorset.__iter__
The method code looks a bit ugly but has good reasons to. We document them
to prevent naive refactoring in the future.
2014-09-16 23:42:41 -07:00
Pierre-Yves David
f7b33aee4f revset: stop using a baseset instead of a plain list in _revsbetween
The function internal code needs a list. Lets use a list.
2014-09-16 22:55:49 -07:00
Pierre-Yves David
10f312d751 revset: simplify orderedlazyset creation in spanset method
We can simply use the `self.isascending` value instead of more complex if/else
clause. This get the code simpler.

Benchmarks show no performances harmed in the process.
2014-09-16 23:47:34 -07:00
Pierre-Yves David
88ccbff938 revset: use spanset.isdescending in multiple simple places
We call the method directly instead of duplicating checks.

Benchmarks show no performances harmed in the process.
2014-09-16 23:37:03 -07:00
Pierre-Yves David
440efac9e4 revset: wider definition of ascending and descending for spanset
Before this patches, empty spanset were seen as neither ascending nor
descending. This is mathematically wrong and create some edges case. We put
`isascending` and `isdescending` back on track so we can use them to simplify
some of the spanset code.

Benchmarks show no performances harmed in the process.
2014-09-16 23:34:18 -07:00
Durham Goode
ce250e375a revset: lower weight for _intlist function
The histedit command uses a revset like:

(_intlist('1234\x001235')) and merge()

Previously the optimizer gave a weight of 1.5 to the _intlist side (1 for the
function, 0.5 for the string) which caused it to process the merge() side first.
This caused it to evaluate merge against every commit in the repo, which took
2.5 seconds on a large repo.

I changed the weight of _intlist to 0, since it's a trivial calculation, which
makes it process intlist first, which makes merge apply only to the revs in the
list. Which makes the revset take 0.15 seconds now. Cutting off 2.4 seconds off
our histedit performance.

>From the revset benchmark:
revset #25: (_intlist('20000\x0020001')) and merge()
0) obsolete feature not enabled but 54243 markers found!
! wall 0.036767 comb 0.040000 user 0.040000 sys 0.000000 (best of 100)
1) obsolete feature not enabled but 54243 markers found!
! wall 0.000198 comb 0.000000 user 0.000000 sys 0.000000 (best of 9084)
2014-09-12 14:21:18 -07:00
Durham Goode
79319b785d revset: make parents() O(number of parents)
Strip executes a revset like this:

max(parents(_intlist('1234\x001235')) - _intlist('1234\x001235'))

Previously the parents() revset would do 'subset & parents' which iterates over
each item in the subset and checks if it's in parents.  subset is usually the
entire repo (a spanset) so this takes a while.

Reversing the parameters to be 'parents & subset' means the operation becomes
O(number of parents) instead of O(size of repo). It also means the result gets
evaluated immediately (since parents isn't a lazy set), but I think this is a
win in most scenarios.

This shaves 0.3 seconds off strip (amend/histedit/rebase/etc) for large repositories.

revset #0: parents(20000)
0) obsolete feature not enabled but 54243 markers found!
! wall 0.006256 comb 0.010000 user 0.010000 sys 0.000000 (best of 289)
1) obsolete feature not enabled but 54243 markers found!
! wall 0.000391 comb 0.000000 user 0.000000 sys 0.000000 (best of 4323)
2014-09-12 15:00:51 -07:00
Durham Goode
9d2bd7f0b2 revset: make descendants() lazier
Previously descendants() would force the provided subset to become a set.  In
the case of revsets like '(%ld::) - (%ld)' (as used by histedit) this would
force the '- (%ld)' set to be evaluated, which produced a set containing every
commit in the repo (except %ld). This takes 0.6s on large repos.

This changes descendants to trust the subset to implement __contains__
efficiently, which improves the above revset to 0.16s. Shaving 0.4 seconds off
of histedit.

revset #27: (20000::) - (20000)
0) obsolete feature not enabled but 54243 markers found!
! wall 0.023640 comb 0.020000 user 0.020000 sys 0.000000 (best of 100)
1) obsolete feature not enabled but 54243 markers found!
! wall 0.019589 comb 0.020000 user 0.020000 sys 0.000000 (best of 100)

This commit removes the final revset related perf hotspot from histedit.
Combined with the previous two patches, they shave a little over 3 seconds off
histedit on large repos.
2014-09-12 16:21:13 -07:00
Michael O'Connor
306b55bcc9 revset: bookmark revset interprets 'literal:' prefix correctly (issue4329) 2014-08-11 23:45:08 -04:00
Gregory Szorc
27315bd014 revset: optimize baseset.__sub__ (issue4313)
f5a63a5506d2 regressed performance of baseset.__sub__ by introducing
a lazyset. This patch restores that lost performance by eagerly
evaluating baseset.__sub__ if the other set is a baseset.

revsetbenchmark.py results impacted by this change:

revset #6: roots(0::tip)
0) wall 2.923473 comb 2.920000 user 2.920000 sys 0.000000 (best of 4)
1) wall 0.077614 comb 0.080000 user 0.080000 sys 0.000000 (best of 100)

revset #23: roots((0:tip)::)
0) wall 2.875178 comb 2.880000 user 2.880000 sys 0.000000 (best of 4)
1) wall 0.154519 comb 0.150000 user 0.150000 sys 0.000000 (best of 61)

On the author's machine, this slowdown manifested during evaluation of
'roots(%ln::)' in phases.retractboundary after unbundling the Firefox
repository. Using `time hg unbundle firefox.hg` as a benchmark:

Before: 8:00
After:  4:28
Delta: -3:32

For reference, the subset and cs baseset instances impacted by this
change were of lengths 193634 and 193627, respectively.

Explicit test coverage of roots(%ln::), while similar to the existing
roots(0::tip) benchmark, has been added.
2014-07-24 12:12:12 -07:00
Matt Harbison
f0308c64dd revset: avoid a ValueError when 'only()' is given an empty set
This previously died in _revdescendants() taking the min() of the first set to
only(), when it was empty.  An empty second set already worked.  Likewise,
descendants() already handled an empty set.
2014-07-18 19:46:56 -04:00
Siddharth Agarwal
5801040e81 revset: remove no longer used _missingancestors revset
This was undocumented.
2014-07-12 00:37:08 -07:00
Siddharth Agarwal
9ea47f6848 revset: replace _missingancestors optimization with only revset
(::a - ::b) is equivalent to only(a, b).
2014-07-12 00:31:36 -07:00
Matt Mackall
5157edb3f5 revset: maintain ordering when subtracting from a baseset (issue4289) 2014-07-14 17:55:31 -05:00
Pierre-Yves David
0a422cd2f2 revset: cosmetic changes in spanset range comparison
We use the python syntax for range comparison: `a < x < c`. This is shorter,
more readable and less error prone. This comparison escaped the cleanup make in
166d6dde9310
2014-04-28 15:14:11 -07:00
Pierre-Yves David
f9553b0f97 revset: drop spanset._contained
All its users inlined it for performance reasons.
(See fcccbf073394 and 166d6dde9310)
2014-04-25 23:38:24 -07:00
Pierre-Yves David
e654410fbc revset: directly use __contains__ instead of a lambda
We get rid of lambda in a bunch of other place. This is equivalent and much
faster. (no new timing as this is the same change as three other changesets)
2014-05-01 14:07:04 -07:00
Pierre-Yves David
b3f19fad6e orderedlazyset: directly use __contains__ instead of a lambda
We apply the same speedup as in spanset, getting rid of the useless lambda.
(No new timing, as this is the very same change)
2014-05-01 12:15:28 -07:00
Pierre-Yves David
68eca34f8d lazyset: directly use __contains__ instead of a lambda
We apply the same speedup as in spanset, getting rid of the useless lambda.
(No new timing, as this is the very same change)
2014-05-01 12:15:00 -07:00
Pierre-Yves David
7a5b8cbf4b spanset: directly use __contains__ instead of a lambda
Spanset are massively used in revset. First because the initial subset itself is
a repo wide spanset. We speed up the __and__ operation by getting rid of a
gratuitous lambda call. A more long terms solution would be to:

1. speed up operation between spansets,
2. have a special smartset for `all` revisions.

In the mean time, this is a very simple fix that buyback some of the performance
regression.

Below is performance benchmark for trival `and` operation between two spansets.
(Run on an unspecified fairly large repository.)

revset tip:0
2.9.2)  wall 0.282543 comb 0.280000 user 0.260000 sys 0.020000 (best of 35)
before) wall 0.819181 comb 0.820000 user 0.820000 sys 0.000000 (best of 12)
after)  wall 0.645358 comb 0.650000 user 0.650000 sys 0.000000 (best of 16)

Proof of concept implementation of an `all` smartset brings this to 0.10 but it's
too invasive for stable.
2014-04-26 00:38:02 -07:00
Pierre-Yves David
a4f88556f4 revset: also inline spanset._contained in __len__
For consistency with what happen in `__contains__`, we inline the range test
into `__len__` too.
2014-04-25 18:00:07 -07:00
Pierre-Yves David
b42c62324c revset: inline spanset containment check (fix perf regression)
Calling a function is super expensive in python. We inline the trivial range
comparison to get back to more sensible performance on common revset operation.

Benchmark result below:

Revision mapping:
0) bced32a3fd6c 2.9.2 release
1) 2ab64f462d81 current @
2) This revision


revset #0: public()
0) wall 0.010890 comb 0.010000 user 0.010000 sys 0.000000 (best of 201)
1) wall 0.012109 comb 0.010000 user 0.010000 sys 0.000000 (best of 199)
2) wall 0.012211 comb 0.020000 user 0.020000 sys 0.000000 (best of 197)

revset #1: :10000 and public()
0) wall 0.007141 comb 0.010000 user 0.010000 sys 0.000000 (best of 361)
1) wall 0.014139 comb 0.010000 user 0.010000 sys 0.000000 (best of 186)
2) wall 0.008334 comb 0.010000 user 0.010000 sys 0.000000 (best of 308)

revset #2: draft()
0) wall 0.009610 comb 0.010000 user 0.010000 sys 0.000000 (best of 279)
1) wall 0.010942 comb 0.010000 user 0.010000 sys 0.000000 (best of 243)
2) wall 0.011036 comb 0.010000 user 0.010000 sys 0.000000 (best of 239)

revset #3: :10000 and draft()
0) wall 0.006852 comb 0.010000 user 0.010000 sys 0.000000 (best of 383)
1) wall 0.014641 comb 0.010000 user 0.010000 sys 0.000000 (best of 183)
2) wall 0.008314 comb 0.010000 user 0.010000 sys 0.000000 (best of 299)

We can see this changeset gains back the regression for `and` operation on
spanset.  We are still a bit slowerfor the `public()` and `draft()`. Predicates
not touched by this changeset.
2014-04-28 15:15:36 -07:00
Pierre-Yves David
4274fa0b04 revset: fix revision filtering in spanset.contains (regression)
The argument is `x` but the variable tested for filtering is `rev`. `rev`
happens to be a revset methods, ... never part of the filtered revs. This
method is now using `rev` for everything.
2014-04-28 16:28:52 -07:00
Greg Hurrell
89c96d28b3 help: clarify distinction among contains/file/filelog
For a Mercurial new-comer, the distinction between `contains(x)`,
`file(x)`, and `filelog(x)` in the "revsets" help page may not be
obvious. This commit tries to make things more obvious (text based on
an explanation from Matt in an FB group thread).
2014-04-28 15:09:23 -07:00
Wagner Bruna
0db6df4ed7 revset, i18n: add translator comment to "only" 2014-04-22 10:12:13 -03:00
Mads Kiilerich
0e8795ccd6 spelling: fixes from spell checker 2014-04-13 19:01:00 +02:00
Mads Kiilerich
b117005b7c revlog: use context ancestor instead of changelog ancestor
We want to move in this direction.
2014-04-07 23:17:51 +02:00
Durham Goode
eac8ba4613 revset: improve roots revset performance
Previously we would iterate over every item in the subset, checking if it was in
the provided args. This often meant iterating over every rev in the repo.

Now we iterate over the args provided, checking if they exist in the subset.
On a large repo this brings setting phase boundaries (which use this revset
roots(X:: - X::Y)) down from 0.8 seconds to 0.4 seconds.

The "roots((tip~100::) - (tip~100::tip))" revset in revsetbenchmarks shows it
going from 0.12s to 0.10s, so we should be able to catch regressions here in the
future.

This actually introduces a regression in 'roots(all())' (0.2s to 0.26s) since
we're now using spansets, which are slightly slower to do containment checks on.
I believe this trade off is worth it, since it makes the revset O(number of
args) instead of O(size of repo).
2014-03-31 16:03:34 -07:00
Durham Goode
13db32b575 revset: improve _descendants performance
Previously revset._descendants would iterate over the entire subset (which is
often the entire repo) and test if each rev was in the descendants list. This is
really slow on large repos (3+ seconds).

Now we iterate over the descendants and test if they're in the subset.
This affects advancing and retracting the phase boundary (3.5 seconds down to
0.8 seconds, which is even faster than it was in 2.9). Also affects commands
that move the phase boundary (commit and rebase, presumably).

The new revsetbenchmark indicates an improvement from 0.2 to 0.12 seconds. So
future revset changes should be able to notice regressions.

I removed a bad test. It was recently added and tested '1:: and reverse(all())',
which has an amibiguous output direction.  Previously it printed in reverse order,
because we iterated over the subset (the reverse part). Now it prints in normal
order because we iterate over the 1:: . Since the revset itself doesn't imply an
order, I removed the test.
2014-03-25 14:10:01 -07:00
Pierre-Yves David
3a1c934d6a revset: raise ValueError when calling min or max on empty smartset
min([]) raise a ValueError, we do the same thing in smartset.min() and
smartset.max() for the sake of consistency.

The min/amax test are greatly improved in the process to prevent this familly
of regression
2014-03-28 17:00:13 -07:00
Pierre-Yves David
4e0cea0c36 _addset: add a __len__ method
Back in the time where repo.revs(...) returned a list, calling `len(...)` on the
result was quite common. We reinstall this on _addset.

There is absolutely no easy way to test this from the command line. The commands
using this in the evolve extension will eventually land into core.
2014-03-20 18:55:28 -07:00
Durham Goode
dd74d4bd47 revset: fix generatorset race condition
If two things were iterating over a generatorset at the same time, they could
miss out on the things the other was generating, resulting in incomplete
results. This fixes it by making it possible for two things to iterate at once,
by always checking the _genlist at the beginning of each iteration.

I was only able to repro it with pending changes from my other commits, but they
aren't ready yet. So I'm unable to add a test for now.
2014-03-25 16:10:07 -07:00
Matt Mackall
b465bcd596 merge with stable 2014-03-25 16:17:16 -05:00
Gregory Szorc
2e930ae769 revset: improve performance of _generatorset.__contains__ (issue 4201)
_generatorset.__contains__ and __contains__ from child classes were
calling into __iter__ to look for values. Since all
previously-encountered values from the generator were cached and checked
in __contains__ before this iteration, __contains__ was effectively
performing iteration busy work which could lead to an explosion of
redundant work.

This patch changes __contains__ to be more intelligent. Instead of
looking at all values via __iter__, __contains__ will instead go
straight to "new" values from the underlying generator.

On a clone of the Firefox repository with around 200,000 changesets,
this patch decreases the execution time of the revset '::(200067)::'
from ~100s to ~4s on the author's machine. Rebase operations (which use
the aforementioned revset), speed up accordingly.
2014-03-24 20:00:18 -07:00
Matt Harbison
60d20455df revset: document the regular expression support for tag(name)
This has been supported since 0041ea008c64, in 2.3.
2014-03-24 21:27:40 -04:00
Matt Mackall
4436b1c4a4 revset: try to handle hyphenated symbols if lookup callback is available
Formerly an expression like "2.4-rc::" was tokenized as 2.4|-|rc|::.
This allows dashes in symbols iff the whole symbol-like string can be
looked up. Otherwise, it's tokenized as a series of symbols and
operators.

No attempt is made to accept dashed symbols inside larger symbol-like
string, for instance foo-bar or bar-baz inside foo-bar-baz.
2014-03-18 17:54:42 -05:00
Matt Mackall
a9a943eddd revset: pass a lookup function to the tokenizer 2014-03-18 17:19:44 -05:00
Lucas Moscovicz
1ff08e4b20 revset: changed minrev and maxrev implementations to use ordered sets
Performance Benchmarking:

0) max(tip:0)
1) min(0:tip)
2) min(0::)

c6d901b5cf89 (2.9.1 release)

    0) ! wall 0.005699 comb 0.000000 user 0.000000 sys 0.000000 (best of 450)
    1) ! wall 0.005414 comb 0.010000 user 0.010000 sys 0.000000 (best of 493)
    2) ! wall 0.025951 comb 0.030000 user 0.030000 sys 0.000000 (best of 107)

a9da3f4c0086 (public tip at submission time)

    0) ! wall 0.015177 comb 0.020000 user 0.020000 sys 0.000000 (best of 175)
    1) ! wall 0.014779 comb 0.010000 user 0.010000 sys 0.000000 (best of 189)
    2) ! wall 12.345179 comb 12.350000 user 12.350000 sys 0.000000 (best of 3)

Current patches:

    0) ! wall 0.001911 comb 0.000000 user 0.000000 sys 0.000000 (best of 1357)
    1) ! wall 0.001943 comb 0.010000 user 0.010000 sys 0.000000 (best of 1406)
    2) ! wall 0.000405 comb 0.000000 user 0.000000 sys 0.000000 (best of 6761)
2014-02-18 11:35:03 -08:00
Lucas Moscovicz
3bb3a9b599 revset: changed addset to extend _orderedsetmixin
Now _addset can use the lazy min and max implementation.
2014-03-14 14:43:44 -07:00
Pierre-Yves David
5b4ec0c02e revset: add a default argument for baseset.__init__
We are now able to create empty baseset using `baseset()` as we are able to
create empty list with `list()`.
2014-03-14 11:41:26 -07:00
Lucas Moscovicz
b693f7e6e2 revset: changed orderedlazyset to also extend _orderedsetmixin
Now orderedlazyset can use the lazy min and max implementation.
2014-03-13 11:36:45 -07:00
Lucas Moscovicz
6cf940b8a2 revset: changed spanset to extend _orderedsetmixin
Now spanset can use the lazy min and max methods implementation.
2014-03-13 11:36:11 -07:00
Lucas Moscovicz
732d8995dd revset: added _orderedsetmixin class
This class has utility methods for any ordered class to get the min and the
max values.
2014-03-12 16:40:18 -07:00
Lucas Moscovicz
829c2686af revset: added min and max methods to baseset and lazyset
This classes have no particular order so they rely on python min() and max()
implementation. This methods will be implemented in every smartset class in
future patches. For other classes there are lazy implementations that can be
made for this methods.
2014-02-19 09:28:17 -08:00
Pierre-Yves David
74abf98daf revset: add documentation and comment for _generatorset
(clean up some old irrelevant comment in the process)
2014-03-14 10:57:04 -07:00
Pierre-Yves David
170d61865e revset: add some documentation for lazyset 2014-03-14 10:55:03 -07:00
Lucas Moscovicz
6f3e54ea87 revset: added documentation and comment for spanset class 2014-03-14 10:59:51 -07:00
Lucas Moscovicz
432476d8c0 revset: changed smartset methods to return ordered addsets
Now when adding two structures that are ordered, they are wrapped into an
_addset and they get added lazily while keeping the order.
2014-03-11 17:25:53 -07:00
Lucas Moscovicz
dd9f8534d9 revset: added isascending and isdescending methods to _addset
This methods are intended to duck-type baseset, so we will still have _addset
as a private class but now we can return it without wrapping it into an
orderedlazyset or a lazyset.

These were the last methods to add for smartset compatibility.
2014-03-14 10:24:09 -07:00
Lucas Moscovicz
c5a9f97171 revset: added __add__ method to _addset
This method is intended to duck-type baseset, so we will still have _addset as a
private class but we will be able to return it without wrapping it into an
orderedlazyset or a lazyset.
2014-03-14 10:23:54 -07:00
Lucas Moscovicz
a79e6ad5a0 revset: added __sub__ mehtod to _addset
This method is intended to duck-type baseset, so we will still have _addset as a
private class but now will be able to return it without wrapping it into an
orderedlazyset or a lazyset.
2014-03-14 10:22:51 -07:00
Lucas Moscovicz
02e069f77d revset: added __and__ method to _addset
This method is intended to duck-type baseset, so we will still have _addset as a
private class but  we will be able to return it without wrapping it into an
orderedlazyset or a lazyset.
2014-03-14 10:22:29 -07:00
Lucas Moscovicz
73a28cdab8 revset: added ascending and descending methods to _addset
This methods are intended to duck-type baseset, so we will still have _addset
as a private class but will be able return it without wrapping it into an
orderedlazyset or a lazyset.
2014-03-14 10:21:56 -07:00
Lucas Moscovicz
e603775f94 revset: added filter method to _addset
This method is intended to duck-type baseset, so we will still have _addset
as a private class but we will be able return it without wrapping it into an
orderedlazyset or a lazyset.
2014-03-13 19:12:36 -07:00
Lucas Moscovicz
8adde22fdb revset: added comments to all methods needed to duck-type from baseset
All this methods are required to duck-type for any class that works as a smart
set.
2014-03-14 09:18:14 -07:00
Lucas Moscovicz
23a1573060 revset: use more explicit argument names for baseset methods
Use other instead of x and condition instead of l
2014-03-14 10:10:18 -07:00
Lucas Moscovicz
1e32ffe0b9 revset: added isascending and isdescending methods to smartset classes
This methods state if the class is sorted in an ascending or descending order

We need this to implement methods based on order on smartset classes in order
to be able to create new objects with a given order.

We cannot just rely on a simple boolean since unordered set are neither
ascending nor descending.
2014-03-11 17:09:23 -07:00
Lucas Moscovicz
8004a27cbf revset: added sort method in addset
We need this method to duck-type generatorset since this class is not going to
be used outside revset.py and we don't need to duck-type baseset.

This sort method will only do something when the addset is not already sorted
or is not sorted in the way we want it to be.
2014-03-11 17:03:43 -07:00
Lucas Moscovicz
62c7bb9117 revset: added reverse method to addset
This method is needed to duck type generatorset.
2014-03-13 18:57:30 -07:00
Lucas Moscovicz
e5f79a44be revset: changed _iterator() method on addset to work with a given order
If the two collections are in ascending order, yield their values in an
ordered way by iterating both at the same time and picking the values to
yield.
2014-03-13 13:29:04 -07:00
Lucas Moscovicz
f2b80f803a revset: changed _iterator() in addset to use the generated list when available
Now when all the elements have been generated, the iterator will just use the
generated list instead of going through all the elements again.
2014-03-13 14:51:04 -07:00
Lucas Moscovicz
1a5e79571b revset: added cached generated list to addset
This way when all the values have been generated the list can be sorted
without having to generate them all again.
2014-03-11 16:59:42 -07:00
Lucas Moscovicz
67d42c8519 revset: changed sort method to use native sort implementation of smartsets
When sort is done by revision or reversed revision number it can just call
sort on the set and doesn't have to iterate it all over again.
2014-03-13 17:15:21 -07:00
Lucas Moscovicz
6da2a5ca22 revset: fixed sorting issue with spanset
When a spanset was being sorted it didn't take into account it's current
state (ascending or descending) and it reversed itself everytime the reverse
parameter was True.

This is not yet used but it will be as soon as the sort revset is changed to
directly use the structures sort method.
2014-03-13 17:16:58 -07:00
Lucas Moscovicz
edbf51ad8f revset: added __nonzero__ method to spanset class
Implemented it in a lazy way, just look for the first non-filtered revision
and return True if there's any revision at all.
2014-03-14 09:07:59 -07:00
Lucas Moscovicz
04e9ab0a9b revset: optimized sort method in lazyset class
We are taking advantage of the smartset classes sort method when it exists and
converting the set to a baseset otherwise.
2014-03-06 09:41:47 -08:00
Durham Goode
f906635299 revset: improve head revset performance
Previously the head() revset would iterate over every item in the subset and
check if it was a head.  Since the subset is often the entire repo, this was
slow on large repos. Now we iterate over each item in the head list and check if
it's in the subset, which results in much less work.

hg log -r 'head()' on a large repo:
Before: 0.95s
After: 0.28s
2014-03-13 13:47:21 -07:00
Lucas Moscovicz
36702af6f9 revset: added ascending attribute to addset class
In case both collections are in an ascending/descending order then we will be
able to iterate them lazily while keeping the order.
2014-03-11 16:52:15 -07:00
Lucas Moscovicz
7da57d658a revset: added set method to addset to duck type generatorset
Since this class is only going to be used inside revset.py (it does not duck
type baseset) it needs to duck type only a few more methods for the next
patches.
2014-03-10 10:49:04 -07:00
Matt Mackall
064d711c69 revsets: backout f497f83593d8 due to performance regressions 2014-03-13 14:34:32 -05:00
Lucas Moscovicz
efb319fb76 revset: made addset a private class
This class is not supposed to be used outside revset.py since it only
wraps content that is used by baseset typed classes.

It only gets created by revset operations or private methods.
2014-03-12 17:20:26 -07:00
Lucas Moscovicz
a50567190d revset: made descgeneratorset a private class
This class is not supposed to be used outside revset.py since it only
wraps content that is used by baseset typed classes.

It only gets created by revset operations or private methods.
2014-03-12 17:19:46 -07:00
Lucas Moscovicz
e6b1cc49b9 revset: made ascgeneratorset a private class
This class is not supposed to be used outside revset.py since it only
wraps content that is used by baseset typed classes.

It only gets created by revset operations or private methods.
2014-03-12 17:18:54 -07:00
Lucas Moscovicz
7e33d4c691 revset: made generatorset a private class
This class are not supposed to be used outside revset.py since it only
wraps content that is used by baseset typed classes.

It only gets created by revset operations or private methods.
2014-03-12 17:07:38 -07:00
Lucas Moscovicz
2c2b32444e revset: added sort methods to generatorsets
Method needed to propagate sort calls amongst lazy structures.
The generated list (stored in the object) is sorted.

If the generated list did not contain all elements from the generator, we
take care of that before sorting the list.
2014-02-24 16:36:17 -08:00
Lucas Moscovicz
9db776218f revset: changed __add__ methods on lazy sets to return addsets (issue4191)
Performance Benchmarking:

$ hg --time log --graph --style compact --limit 6 -r 'sort((::. or bookmark()
or heads(public())), "-rev")'
time: real 1.540 secs (user 1.510+0.000 sys 0.020+0.000)

$ ./hg --time log --graph --style compact --limit 6 -r 'sort((::. or
bookmark() or heads(public())), "-rev")'
time: real 1.240 secs (user 1.190+0.000 sys 0.040+0.010)
2014-03-07 14:06:49 -08:00
Lucas Moscovicz
82e3bb4e2c revset: added addset class with its basic methods
This class addresses the problem of losing performance on the __contains__
method when adding two smart structures with fast membership testing.
2014-03-07 13:48:31 -08:00
Lucas Moscovicz
a47624e9b5 revset: changed _children method to use lazy structures 2014-02-11 14:03:43 -08:00
Lucas Moscovicz
c7b531ba29 revset: changed descendants revset to use lazy generators
Performance Benchmarking:

$ time hg log -qr "0:: and 0:5"
...

real  0m3.665s
user  0m3.364s
sys 0m0.289s

$ time ./hg log -qr "0:: and 0:5"
...

real  0m0.492s
user  0m0.394s
sys 0m0.097s
2014-02-10 12:26:45 -08:00
Lucas Moscovicz
ead9ef7efc revset: optimized _revancestors method based on order of revisions
If the revisions for which the ancestors are required are in descending order,
it lazily loads them into a heap to be able to yield values faster.
2014-02-07 13:44:57 -08:00
Lucas Moscovicz
8456e8d71a revset: changed ancestors revset to return lazy generators
This will not improve revsets like "::tip" but will do when that gets
intersected or substracted with another revset.

Performance Benchmarking:

$ time hg log -qr "draft() and ::tip"
...

real  0m3.961s
user  0m3.640s
sys 0m0.313s

$ time ./hg log -qr "draft() and ::tip"
...

real  0m1.080s
user  0m0.987s
sys 0m0.083s
2014-02-07 10:32:02 -08:00
Lucas Moscovicz
4a4c0782a7 revset: changed methods in spanset to return ordered sets
Now __sub__ and __and__ can smartly return ordered lazysets.
2014-02-18 13:07:08 -08:00
Lucas Moscovicz
82070b57ca revset: added sort method to orderedlazyset 2014-02-25 10:36:23 -08:00
Lucas Moscovicz
9ade74466e revset: added order methods to lazyset classes
This will allow revsets to ask for an ordered set when possible to be able to
work lazily with it.
2014-02-07 08:44:18 -08:00
Lucas Moscovicz
e87d3ac6ae revset: added ordered generatorset classes with __contains__ method
They stop iterating as soon as they go past the value they are looking for,
so, for values not in the generator they return faster.
2014-02-27 17:27:03 -08:00
Lucas Moscovicz
d710c5103e revset: changed generatorset code to remove unnecesary function call
Removed _nextitem() method, now __iter__ has that logic and __contains__ uses
__iter__ to check for membership.
2014-03-03 12:54:46 -08:00
Durham Goode
f2e7078d1a revset: add 'only' revset
Adds a only() revset that has two forms:

only(<set>) is equivalent to "::<set> - ::(heads() - heads(<set>::))"

only(<include>,<exclude>) is equivalent to "::<include> - ::<exclude>"

On a large repo, this implementation can process/traverse 50,000 revs in 0.7
seconds, versus 4.2 seconds using "::<include> - ::<exclude>".

This is useful for performing histedits on your branch:
hg histedit -r 'first(only(.))'

Or lifting branch foo off of branch bar:
hg rebase -d @ -s 'only(foo, bar)'

Or a variety of other uses.
2013-11-16 08:57:08 -08:00
Lucas Moscovicz
fbd41fa2f4 revset: added basic operators to orderedlazyset
Now __and__ and __sub__ return orderedlazyset.
2014-02-06 17:42:08 -08:00
Lucas Moscovicz
66c7004b8c revset: changed revset code to use filter method
Revset methods now use the filter code to apply a condition.
2014-02-06 09:28:41 -08:00
Lucas Moscovicz
e70d62798f revset: added filter method to revset classes
This method will replace the creation of lazysets inside the revset methods.
Instead, the classes that handle lazy structures will create them based on
their current order.
2014-02-06 17:18:11 -08:00
Lucas Moscovicz
2e8fa99be8 revset: added orderedlazyset class 2014-02-05 15:24:08 -08:00
Lucas Moscovicz
5d74d40ff4 revset: changed spanset __add__ implementation to work lazily
$ time hg log -qr "first(0:tip or draft())"
...

real  0m1.032s
user  0m0.841s
sys 0m0.179s

$ time ./hg log -qr "first(0:tip or draft())"
...

real  0m0.378s
user  0m0.291s
sys 0m0.085s
2014-02-13 09:18:16 -08:00
Lucas Moscovicz
3c92337f5c revset: changed lazyset __add__ implementation to work lazily
Performance Benchmarking:

$ time hg log -qr "first(author(mpm) or branch(default))"
0:3a6a38229d41

real  0m3.875s
user  0m3.818s
sys 0m0.051s

$ time ./hg log -qr "first(author(mpm) or branch(default))"
0:3a6a38229d41

real  0m0.213s
user  0m0.174s
sys 0m0.038s
2014-02-13 09:00:25 -08:00
Lucas Moscovicz
df2d5bd9ed revset: added _hexlist method to replace _list for %ln
Now %ln expression goes through _hexlist and doesn't do any unnecesary
processing anymore.
2014-02-26 17:15:55 -08:00
Lucas Moscovicz
d6c47fdc4c revset: added _intlist method to replace _list for %ld
Now %ld expression goes through _intlist and doesn't do any unnecesary
processing anymore.
2014-02-26 12:36:36 -08:00
Lucas Moscovicz
59ef037f26 revset: added __nonzero__ method to lazyset
Now it doesn't have to go through all the set and can return lazily as soon as
it finds one element.
2014-02-20 10:15:38 -08:00
Lucas Moscovicz
b6ae0f9720 revset: added cached generated list on generatorset
This allows to iterate the generatorset more than once.
2014-02-12 18:45:49 -08:00
Lucas Moscovicz
e97b3cbf9e revset: fixed bug where log -f was taking too long to return 2014-02-21 13:16:17 -08:00
Lucas Moscovicz
bee2c6a618 revset: added generatorset class with cached __contains__ method 2014-02-05 15:23:11 -08:00
Lucas Moscovicz
cf5a2af3df revset: changed last implementation to use lazy classes
Instead of using getitem just reverse the revision list and get the first
'lim' elements. With classes like spanset which are easily reversible this
will work faster.

Performance Benchmarking:

$ time hg log -qr "last(all())"
...

real  0m0.569s
user  0m0.447s
sys 0m0.122s

$ time ./hg log -qr "last(all())"
...

real  0m0.215s
user  0m0.150s
sys 0m0.063s
2014-02-19 12:56:41 -08:00
Lucas Moscovicz
131799c6de revset: changed mfunc and getset to work with old style revset methods
Now extensions shouldn't break when adding new revsets.
2014-02-18 15:54:46 -08:00
Lucas Moscovicz
ba7cfe4ed4 revset: changed revsets to use spanset
Performance Benchmarking:

$ hg perfrevset "first(all())"
! wall 0.304936 comb 0.300000 user 0.280000 sys 0.020000 (best of 33)

$ ./hg perfrevset "first(all())"
! wall 0.175640 comb 0.180000 user 0.160000 sys 0.020000 (best of 56)
2014-02-03 10:15:15 -08:00
Lucas Moscovicz
6e0e0d512b revset: changed spanset to take a repo argument
This way, we can have by default the length of the repo as the end argument
and less code has to be aware of hidden revisions.
2014-02-18 11:38:03 -08:00
Lucas Moscovicz
4961b39b44 revset: changed spanset implementation to take hidden revisions into account
Hidden revisions are now excluded from the spanset.
Now this doesn't break for people using changeset evolution.
2014-02-10 17:38:43 -08:00
Lucas Moscovicz
3d8c71a8cc revset: added cache to lazysets
This allows __contains__ to return faster when asked for same value twice.
2014-02-04 15:31:57 -08:00
Siddharth Agarwal
2c51509bb0 revset: optimize missing ancestor expressions
A missing ancestor expression is any expression of the form (::x - ::y) or
equivalent. Such expressions are remarkably common, and so far have involved
multiple walks down the DAG, followed by a set difference operation.

With this patch, such expressions will be transformed into uses of the fast
algorithm at ancestor.missingancestor.

For a repository with over 600,000 revisions, perfrevset for '::tip - ::-10000'
returns:

Before: ! wall 3.999575 comb 4.000000 user 3.910000 sys 0.090000 (best of 3)
After:  ! wall 0.132423 comb 0.130000 user 0.130000 sys 0.000000 (best of 75)
2014-02-13 14:04:47 -08:00
Siddharth Agarwal
2a56880ad4 revset: add an undocumented _missingancestors function
This will be used in an upcoming patch to optimize expressions of the form
(::x - ::y).
2014-02-13 13:54:45 -08:00
Lucas Moscovicz
3a2188dac4 revset: added operations to spanset to duck type baseset
Added more operations which are not lazy but only used so far to duck type
baseset.
2014-02-06 15:56:25 -08:00
Lucas Moscovicz
e8f60a5520 revset: added basic operations to spanset
Added methods __add__, __sub__ and __and__ to duck type more methods in
baseset
2014-02-12 10:22:43 -08:00
Lucas Moscovicz
9ce7f8243d revset: added spanset class to represent revision ranges 2014-02-12 10:16:21 -08:00
Lucas Moscovicz
97db49c09a revset: added lazyset implementation to extra revset 2014-02-06 08:36:11 -08:00
Lucas Moscovicz
1d43685667 revset: added lazyset implementation to converted revset 2014-02-06 08:32:40 -08:00
Lucas Moscovicz
a871b2cef1 revset: added lazyset implementation to closed revset 2014-02-06 08:31:55 -08:00
Lucas Moscovicz
082b56b0fb revset: added lazyset implementation to contains revset 2014-02-04 15:07:03 -08:00
Lucas Moscovicz
7a6459e30d revset: added lazyset implementation to secret revset 2014-02-04 09:29:19 -08:00
Lucas Moscovicz
c27606d6ba revset: added lazyset implementation to matching revset
Performance Benchmarking:

$ time hg log -qr "first(matching(0))"
0:3a6a38229d41

real  0m2.213s
user  0m2.149s
sys 0m0.055s

$ time ./hg log -qr "first(matching(0))"
0:3a6a38229d41

real  0m0.177s
user  0m0.137s
sys 0m0.038s
2014-02-04 09:14:45 -08:00
Lucas Moscovicz
2f1f581a8c revset: added lazyset implementation to _matchfiles
Performance Benchmarking:

$ time hg log -qr "first(file(README))"
0:3a6a38229d41

real  0m2.234s
user  0m2.180s
sys 0m0.044s

$ time ./hg log -qr "first(file(README))"
0:3a6a38229d41

real  0m0.172s
user  0m0.129s
sys 0m0.042s
2014-02-04 08:51:07 -08:00
Lucas Moscovicz
3bfbd34602 revset: added lazyset implementation to checkstatus
This improves the performance of the revsets 'adds' 'modifies' and 'removes'

Performance benchmarking:

$ time hg log -qr "first(adds(README))"
0:3a6a38229d41

real  0m2.279s
user  0m2.222s
sys 0m0.053s

$ time ./hg log -qr "first(adds(README))"
0:3a6a38229d41

real  0m0.172s
user  0m0.131s
sys 0m0.041s

$ time hg log -qr "first(modifies(README))"
1:692bee203f23

real  0m2.292s
user  0m2.227s
sys 0m0.061s

$ time ./hg log -qr "first(modifies(README))"
1:692bee203f23

real  0m0.178s
user  0m0.130s
sys 0m0.038s

$ time hg log -qr "first(removes(README))"
2379:f24de2acd560

real  0m2.297s
user  0m2.235s
sys 0m0.058s

$ time ./hg log -qr "first(removes(README))"
2379:f24de2acd560

real  0m0.975s
user  0m0.797s
sys 0m0.056s
2014-01-31 10:47:51 -08:00
Lucas Moscovicz
8cb1ccfe44 revset: added lazyset implementation to public revset
Performance Benchmarking:

$ time hg log -qr "first(public())"
...

real  0m1.184s
user  0m1.051s
sys 0m0.130s

$ time ./hg log -qr "first(public())"
...

real  0m0.548s
user  0m0.427s
sys 0m0.118s
2014-01-30 17:46:08 -08:00
Lucas Moscovicz
69d62676c5 revset: added lazyset implementation to merge revset
Performance benchmarking:

$ time hg log -qr "first(merge())"
102:1634643e0cd8

real  0m0.276s
user  0m0.208s
sys 0m0.047s

$ time ./hg log -qr "first(merge())"
102:1634643e0cd8

real  0m0.192s
user  0m0.154s
sys 0m0.027s
2014-01-30 16:47:29 -08:00
Lucas Moscovicz
f18b7c26e0 revset: added lazyset implementation to grep revset
Performance benchmarking:

$ time hg log -qr "first(grep(hg))"
0:3a6a38229d41

real  0m2.214s
user  0m2.163s
sys 0m0.045s

$ time ./hg log -qr "first(grep(hg))"
0:3a6a38229d41

real  0m0.211s
user  0m0.146s
sys 0m0.035s
2014-01-30 16:03:18 -08:00
Lucas Moscovicz
ab42b4bbc5 revset: added lazyset implementation to desc revset
Performance benchmarking:

$ time hg log -qr "first(desc(hg))"
changeset:   0:3a6a38229d41

real  0m2.210s
user  0m2.158s
sys 0m0.049s

$ time ./hg log -qr "first(desc(hg))"
changeset:   0:3a6a38229d41

real  0m0.171s
user  0m0.131s
sys 0m0.035s
2014-01-30 15:39:56 -08:00
Lucas Moscovicz
6ba591c77e revset: added lazyset implementation to draft revset 2014-02-03 16:15:25 -08:00
Lucas Moscovicz
57e67b73a7 revset: added lazyset implementation bookmark revset 2014-01-29 15:23:16 -08:00
Lucas Moscovicz
28688b6d54 revset: added lazyset implementation to date revset
Performance Benchmarking:

$ time hg log -qr "first(date(05/03/2005))"
0:3a6a38229d41

real  0m3.157s
user  0m2.994s
sys 0m0.087s

$ time ./hg log -qr "first(date(05/03/2005))"
0:3a6a38229d41

real  0m0.509s
user  0m0.289s
sys 0m0.070s
2014-02-03 16:02:48 -08:00
Lucas Moscovicz
d80d16c98c revset: added lazyset implementation to author revset
Performance benchmarking:

$ time hg log -qr "first(author(mpm))"
0:3a6a38229d41

real  0m3.486s
user  0m3.317s
sys 0m0.077s

$ time ./hg log -qr "first(author(mpm))"
0:3a6a38229d41

real  0m0.551s
user  0m0.295s
sys 0m0.072s
2014-01-29 09:22:31 -08:00
Lucas Moscovicz
fe40abc599 revset: added lazyset implementation to keyword revset
Performance benchmarking:

$ time hg log -qr "first(keyword(changeset))"
0:3a6a38229d41

real  0m3.466s
user  0m3.345s
sys 0m0.072s

$ time ./hg log -qr "first(keyword(changeset))"
0:3a6a38229d41

real  0m0.365s
user  0m0.199s
sys 0m0.083s
2014-01-29 09:04:03 -08:00
Lucas Moscovicz
303bd9d554 revset: changed limit revset implementation to work with lazy revsets
Performance benchmarking:

$ time hg log -qr "first(branch(default))"
0:3a6a38229d41

real  0m3.130s
user  0m3.025s
sys 0m0.074s

$ time ./hg log -qr "first(branch(default))"
0:3a6a38229d41

real  0m0.300s
user  0m0.198s
sys 0m0.069s
2014-01-28 16:19:30 -08:00
Lucas Moscovicz
7a6ce89407 revset: added lazyset implementation to branch revset
Performance Benchmarking:

$ time hg log -l1 -qr "branch(default)"
0:3a6a38229d41

real  0m3.366s
user  0m3.217s
sys 0m0.095s

$ time ./hg log -l1 -qr "branch(default)"
0:3a6a38229d41

real  0m0.389s
user  0m0.199s
sys 0m0.061s
2014-02-05 16:12:03 -08:00
Lucas Moscovicz
0ff716dae6 revset: changed getset so that it can return a lazyset
Not converting it manually to a baseset anymore. At this point every revset
method should return a baseset typed structure.
2014-01-28 15:19:14 -08:00
Lucas Moscovicz
fb15b99ea8 revset: added operations to duck type baseset
Added more operations which are not lazy but only used so far to duck type
baseset.

Their implementations will be changed in future patches.
2014-02-06 14:29:37 -08:00
Lucas Moscovicz
dd14a88eaa revset: added basic operations to lazyset
Added methods __add__, __sub__ and __and__ to duck type more methods in
baseset
2014-02-06 14:25:37 -08:00
Lucas Moscovicz
939eba25eb revset: added lazyset class with basic operations
This class allows us to return values from large revsets as soon as they are
computed instead of having to wait for the entire revset to be calculated.
2014-02-06 14:19:40 -08:00
Lucas Moscovicz
5ea4d9b527 revset: minor changes adding baseset to revsets
Changed bits of code to work with baseset implementations.
2014-02-06 14:57:25 -08:00
Lucas Moscovicz
c5d089f8a5 revset: minor changes adding baseset to revsets
Changed bits of code to work with baseset implementations.
2014-02-06 14:57:25 -08:00
Lucas Moscovicz
91dcdf4e40 revset: added __add__ method to baseset class 2014-02-06 11:37:16 -08:00
Lucas Moscovicz
03857b594a revset: added docstring to baseset class 2014-02-06 11:33:36 -08:00
Lucas Moscovicz
0c945a320b revset: fixed bug where revset returning order was being changed
Some revsets were innecesarily turning the subset into a set before iterating
over it. This led to returning order changing in some cases.
2014-02-07 15:01:33 -08:00
Lucas Moscovicz
3d0344901f revset: added intersection to baseset class
Added the method __and__ to the baseset class to be able to intersect with
other objects in a more efficient way.
2014-01-24 16:57:44 -08:00
Lucas Moscovicz
f1e6aec1ef revset: added substraction to baseset class
Added __sub__ method to the baseset class to be able to compare it with other
subsets more efficiently.
2014-01-23 14:20:58 -08:00
Lucas Moscovicz
e0e3b9efa2 revset: implemented set caching for revset evaluation
Added set caching to the baseset class. It lazily builds the set whenever it's
needed and keeps a reference which is returned when the set is requested
instead of being built again.
2014-01-22 10:46:02 -08:00
Lucas Moscovicz
ef8bd69f5f revset: added baseset class (still empty) to improve revset performance
This class is going to be used to cache the set that is created from this list
in many cases while evaluating a revset.
2014-01-21 11:39:26 -08:00
FUJIWARA Katsunori
9baf47cf1a revset: add explanation about the pattern without explicit kind
Before this patch, online help of "adds()", "contains()", "filelog()",
"file()", "modifies()" and "removes()" predicates doesn't explain
about how the pattern without explicit kind like "glob:" is treated,
even though each predicates treat it differently:

  - as "relpath:" by "adds()", "modifies()" and "removes()"

  - as "glob:" by "file()"

  - as special by "contains()" and "filelog()"
    - be relative to cwd, and
    - match against a file exactly
      ("relpath:" matches also against a directory)

This may confuse users.

This patch adds explanation about the pattern without explicit kind
to these predicates.
2014-01-17 23:55:11 +09:00
FUJIWARA Katsunori
92ff577d38 revset: use "canonpath()" for "filelog()" pattern without explicit kind
Before this patch, revset predicate "filelog()" uses "match.files()"
to get filename also for the pattern without explicit kind.

But in such case, only canonicalization of relative path is required,
and other initializations of "match" object including regexp
compilation are meaningless.

This patch uses "pathutil.canonpath()" directly for "filelog()"
pattern without explicit kind like "glob:", for efficiency.

This patch also does below as a part of introducing "canonpath()":

  - move location of "matchmod.match()" invocation, because "m" is no
    more used in "if not matchmod.patkind(pat)" code path

  - omit passing "default" argument to "matchmod.match()", because
    "pat" should have explicit kind of pattern in this code path
2014-01-17 23:55:03 +09:00
FUJIWARA Katsunori
4d5d9b1517 revset: avoid loop for "match.files()" having always one element for efficiency
This patch avoids the loop for "match.files()" having always one
element in revset predicate "filelog()" for efficiency: "match" object
"m" is constructed with "[pat]" as "patterns" argument.
2014-01-17 23:42:12 +09:00
FUJIWARA Katsunori
7e4fbdb87b revset: make default kind of pattern for "contains()" rooted at cwd
Before this patch, default kind of pattern for revset predicate
"contains()" is treated as the exact file path rooted at the root of
the repository. This decreases usability, because:

  - all other predicates taking pattern argument (also "filelog()")
    treat such pattern as the path rooted at the current working
    directory

  - "contains()" doesn't describe this difference in its help

  - this difference may confuse users

    for example, this prevents revset aliases from sharing same
    argument between "contains()" and other predicates


This patch makes default kind of pattern for revset predicate
"contains()" be rooted at the current working directory.

This patch uses "pathutil.canonpath()" instead of creating "match"
object for efficiency.
2014-01-17 23:42:12 +09:00
FUJIWARA Katsunori
43338be810 revset: narrow scope of the variable referred only in specific code path
This patch narrows scope of the variable "m" in the function for
revset predicate "contains()", because it is referred only in "else"
code path of "if not matchmod.patkind(pat)" examination.
2014-01-17 23:42:12 +09:00
Yuya Nishihara
cb7a1dd14c fileset, revset: do not use global parser object for thread safety
parse() cannot be called at the same time because a parser object keeps its
states.  This is no problem for command-line hg client, but it would cause
strange errors in multi-threaded hgweb.

Creating parser object is not too expensive.

original:
% python -m timeit -s 'from mercurial import revset' 'revset.parse("0::tip")'
100000 loops, best of 3: 11.3 usec per loop

thread-safe:
% python -m timeit -s 'from mercurial import revset' 'revset.parse("0::tip")'
100000 loops, best of 3: 13.1 usec per loop
2013-12-21 12:44:19 +09:00
Alexander Plavin
d519eef8ec revset: add a whitelist of DoS-safe symbols
'Safe' here means that they can't be used for a DoS attack for any given input.
2013-09-06 13:30:56 +04:00
Alexander Plavin
75dc3d55d6 revset: add helper function to get functions used in a revset parse tree
Will be used to determine whether all functions used in a hgweb search query
are allowed there.
2013-08-07 01:21:31 +04:00
Alexander Plavin
573b3e69b6 revset: add helper function to get revset parse tree depth
Will be used to determine if a hgweb search query actually uses
any revset syntax.
2013-08-09 22:52:58 +04:00
Alexander Plavin
fd04e86dd0 revset: fix wrong keyword() behaviour for strings with spaces
Some changesets can be wrongly reported as matched by this predicate
due to searching in a string joined with spaces and not individually.
A test case added, which fails without this fix.
2013-08-06 00:52:06 +04:00
Alexander Plavin
829cf92d16 log: fix behavior with empty repositories (issue3497)
Make output in this special case consistent with general case one.
2013-04-17 00:29:54 +04:00
Kevin Bullock
8d329cb6b6 revset: don't abort when regex to tag() matches nothing (issue3850)
This makes the tag("re:...") revset consistent with branch("re:...").
2013-03-18 16:04:10 -05:00
Paul Cavallaro
4a3134830c revset: change ancestor to accept 0 or more arguments (issue3750)
Change ancestor to accept 0 or more arguments. The greatest common ancestor of a
single changeset is that changeset. If passed no arguments, the empty list is
returned.
2013-01-28 12:19:21 -08:00
Kevin Bullock
921b868783 bookmarks: don't use bookmarks.listbookmarks in local computations
bookmarks.listbookmarks is for wire-protocol use. The normal way to get
all the bookmarks on a local repository is repo._bookmarks.
2013-01-27 14:24:37 -06:00
FUJIWARA Katsunori
1fc2644404 revset: evaluate sub expressions correctly (issue3775)
Before this patch, sub expression may return unexpected result, if it
is joined with another expression by "or":

  - "^"/parentspec():
    "R or R^1" is not equal to "R^1 or R". the former returns only "R".

  - "~"/ancestorspec():
    "R or R~1" is not equal to "R~1 or R". the former returns only "R".

  - ":"/rangeset():
    "10 or (10 or 15):" is not equal to "(10 or 15): or 10". the
    former returns only 10 and 15 or grater (11 to 14 are not
    included).

In "or"-ed expression "A or B", the "subset" passed to evaluation of
"B" doesn't contain revisions gotten from evaluation of "A", for
efficiency.

In the other hand, "stringset()" fails to look corresponding revision
for specified string/symbol up, if "subset" doesn't contain that
revision.

So, predicates looking revisions up indirectly should evaluate sub
expressions of themselves not with passed "subset" but with "entire
revisions in the repository", to prevent "stringset()" from unexpected
failing to look symbols in them up.

But predicates in above example don't so. For example, in the case of
"R or R^1":

  1. "R^1" is evaluated with "subset" containing revisions other than
     "R", because "R" is already gotten by the former of "or"-ed
     expressions

  2. "parentspec()" evaluates "R" of "R^1" with such "subset"

  3. "stringset()" fails to look "R" up, because "R" is not contained
     in "subset"

  4. so, evaluation of "R^1" returns no revision

This patch evaluates sub expressions for predicates above with "entire
revisions in the repository".
2013-01-23 22:52:55 +09:00
Mads Kiilerich
7bc546e4e0 bundlerepo: improve performance for bundle() revset expression
Create the set of revision numbers directly instead of creating a list of nodes
first.
2013-01-16 20:41:34 +01:00
Kevin Bullock
93f9cb7f25 filtering: rename filters to their antonyms
Now that changelog filtering is in place, it's become evident that
naming the filters according to the set of revs _not_ included in the
filtered changelog is confusing. This is especially evident in the
collaborative branch cache scheme.

This changes the names of the filters to reflect the revs that _are_
included:

  hidden -> visible
  unserved -> served
  mutable -> immutable
  impactable -> base

repoview.filteredrevs is renamed to filterrevs, so that callers read a
bit more sensibly, e.g.:

  filterrevs('visible') # filter revs according to what's visible
2013-01-13 01:39:16 -06:00
Pierre-Yves David
10fc5e09ff revset: retrieve hidden from filteredrevs
This prepare the dropping of the `repo.hiddenrevs` property
2013-01-03 18:48:14 +01:00
Pierre-Yves David
f3faf259c5 obsolete: add revset and test for divergent changesets
This changesets add a new `divergent()` revset similar to `unstable()` and
`bumped()` one. Introducting this revset allows actuall test of the divergent
detection.
2012-12-12 03:12:55 +01:00
Siddharth Agarwal
86e87e5ede revset.children: ignore rev numbers that are too low
This replaces unnecessary parentrevs() calls with calculating min(parentset).
Even though the min operation is O(size of parentset), since parentrevs is
relatively expensive, this tradeoff almost always works in our favour. In a
repository with over 400,000 changesets, hg perfrevset "children(X)" takes:

       Set X       Before    After
       -1           0.51s    0.06s
    -1000:          0.55s    0.08s
   -10000:          0.56s    0.10s
  -100000:          0.60s    0.25s
  -100000:-99000    0.55s    0.19s
        0:100000    0.60s    0.61s
      all()         0.72s    0.74s

The relative performance is similar for Mercurial's own repository -- several
times faster in most cases, slightly slower for revisions close to 0 and
all().
2012-12-07 10:37:43 -08:00
Matt Mackall
cf4605492a merge with stable 2012-11-28 16:15:05 -06:00
Matt Mackall
d4deebc4f7 revset: backed out changeset 7a8dc9a35aa2
This was causing clones of the hg repo to go from 12.4s to 14.7s.
2012-11-26 13:44:11 -06:00
Durham Goode
6a6b8c49d1 commit: increase perf by avoiding checks against entire repo subsets
When commiting to a repo with lots of history (>400000 changesets)
checking the results of revset.py:descendants against the subset takes
some time.  Since the subset equals the entire changelog, the check
isn't necessary.  Avoiding it in that case saves 0.1 seconds off of
a 1.78 second commit. A 6% gain.

We use the length of the subset to determine if it is the entire repo.
There is precedence for this in revset.py:stringset.
2012-11-16 15:39:12 -08:00
Matt Mackall
e56ab4a814 revset: accept @ in unquoted symbols (issue3686) 2012-10-30 18:48:44 -05:00
Bryan O'Sullivan
e9f10aaaf1 Merge with crew-stable 2012-11-20 10:09:06 -08:00
Tomasz Kleczek
fab490ae63 bundle: add revset expression to show bundle contents (issue3487)
bundle() revset expression returns all changes that are present
in the bundle file (no matter whether they are in the repo or not).

Bundle file should be specified via -R option.
2012-10-31 16:23:23 -07:00
Pierre-Yves David
6f4d6c0cd4 revset: add a bumped revset
Select bumped changesets.
2012-10-19 00:39:06 +02:00
Pierre-Yves David
bc08c6dbf1 obsolete: rename getobscache into getrevs
The old name was not very good for two reasons:
- caller does not care about "cache",
- set of revision returned may not be obsolete at all.

The new name was suggested by Kevin Bullock.
2012-10-19 00:28:13 +02:00
Pierre-Yves David
99b5dd9737 clfilter: remove use of xrange in revset
For changelog level filtering to take effect it need to be used for any
iteration. Some remaining use of `xrange` in revset code is replace by proper
use of `changelog.revs` or direct iteration over changelog.
2012-10-08 15:54:53 +02:00
Pierre-Yves David
abf7ca7986 branchpoint: remove useless intermediate set creation
We don't need to compute the set of all branchpoints. We can just check the
number of children that element of subset have. The extra work did not seems to
had particular performance impact but the code is simpler this way.
2012-10-15 17:43:05 +02:00
Pierre-Yves David
dcd3550206 clfilter: use changelog to iterate over the repo in branchpoint
Otherwise filtered changesets may cause false positives in `branchpoint()`.
2012-10-15 17:42:40 +02:00
Ivan Andrus
3a1f5d9617 revsets: add branchpoint() function
The branchpoint() function returns changesets with more than one child.
Eventually I would like to be able to see only branch points and merge
points in a graphical log to see the topology of the repository.
2012-08-13 21:50:45 +02:00
Pierre-Yves David
df82aab75f clfilter: remove usage of range in favor of iteration over changelog
If we want to apply filtering at changelog level, we need to iterate over it.
See previous changeset description for details.
2012-09-20 19:01:53 +02:00
Pierre-Yves David
785d90eba0 obsolete: introduce caches for all meaningful sets
This changeset introduces caches on the `obsstore` that keeps track of sets of
revisions meaningful for obsolescence related logics. For now they are:

- obsolete: changesets used as precursors (and not public),
- extinct:  obsolete changesets with osbolete descendants only,
- unstable: non obsolete changesets with obsolete ancestors.

The cache is accessed using the `getobscache(repo, '<set-name>')` function which
builds the cache on demand. The `clearobscaches(repo)` function takes care of
clearing the caches if any.

Caches are cleared when one of these events happens:

- a new marker is added,
- a new changeset is added,
- some changesets are made public,
- some public changesets are demoted to draft or secret.

Declaration of more sets is made easy because we will have to handle at least
two other "troubles" (latecomer and conflicting).

Caches are now used by revset and changectx. It is usually not much more
expensive to compute the whole set than to check the property of a few elements.
The performance boost is welcome in case we apply obsolescence logic on a lot of
revisions. This makes the feature usable!
2012-08-28 20:52:04 +02:00
Mads Kiilerich
2f4504e446 fix trivial spelling errors 2012-08-15 22:38:42 +02:00
Patrick Mezard
7acf48f9a1 revset: add hidden() revset 2012-08-04 20:20:48 +02:00
Patrick Mezard
b5860803d6 revset: minor doc fixes on obsolete related revsets 2012-07-30 15:48:04 +02:00
FUJIWARA Katsunori
b4636b9d05 revset: fix the definition of "unstable changesets" for "unstable" predicate
unstable-ness of changesets should be determined by obsolete-ness of
not descendants but ancestors.
2012-07-28 23:51:57 +09:00
Greg Ward
9468b4b81c revset: polish explanation of the difference between file() and filelog() 2012-07-25 22:41:26 -04:00
FUJIWARA Katsunori
5f3de0edc0 i18n: add/relocate "i18n keyword" comments for i18n messages in revset.py 2012-07-26 13:58:43 +09:00
FUJIWARA Katsunori
26c5c2b610 revset: use appropriate predicate name in error messages
"extinct" and "unstable" predicates use "obsolete" implementation
internally, but own predicate name should be used in error messages of
them instead of "obsolete".
2012-07-26 13:58:43 +09:00
FUJIWARA Katsunori
cc080612f7 revset: add explanation about difference between 'filelog()' and 'file()' 2012-07-25 16:15:28 +09:00
Matt Harbison
223186cb48 revset: add destination() predicate
This predicate is used to find csets that were created because of a graft,
transplant or rebase --keep.  An optional revset can be supplied, in which case
the result will be limited to those copies which specified one of the revs as
the source for the command.

    hg log -r destination()                 # csets copied from anywhere
    hg log -r destination(branch(default))  # all csets copied from default

    hg log -r origin(x) or destination(origin(x))  # all instances of x

This predicate will follow a cset through different types of copies.  Given a
repo with a cset 'S' that is grafted to create G(S), which itself is
transplanted to become T(G(S)):

    o-S
   /
  o-o-G(S)
   \
    o-T(G(S))

    hg log -r destination( S )    # { G(S), T(G(S)) }
    hg log -r destination( G(S) ) # { T(G(S)) }

The implementation differences between the three different copy commands (see
the origin() predicate) are not intentionally exposed, however if the
transplant was a graft instead:

	hg log -r destination( G(S) )   # {}

because the 'extra' field in G(G(S)) is S, not G(S).  The implementation cannot
correct this by following sources before G(S) and then select the csets that
reference those sources because the cset provided to the predicate would also
end up selected.  If there were more than two copies, sources of the argument
would also get selected.

Note that the convert extension does not currently update the 'extra' map in its
destination csets, and therefore copies made prior to the convert will be
missing from the resulting set.

Instead of the loop over 'subset', the following almost works, but does not
select a transplant of a transplant.  That is, 'destination(S)' will only
select T(S).

    dests = set([r for r in subset if _getrevsource(repo, r) in args])
2012-07-07 00:47:55 -04:00
Matt Harbison
f78efc8aa9 revset: add origin() predicate
This predicate is used to find the original source of csets created by a graft,
transplant or rebase --keep.  If a copied cset is itself copied, only the
source of the original copy is selected.

    hg log -r origin()                # all src csets, anywhere
    hg log -r origin(branch(default)) # all srcs of copies on default

By following through different types of copy commands and only selecting the
original cset, the implementation differences between the copy commands are
hidden.  (A graft of a graft preserves the original source in its 'extra' map,
while transplant and rebase use the immediate source specified for the
command).

Given a repo with a cset S that is grafted to create G(S), which itself is
grafted to become G(G(S))

    o-S
   /
  o-o-G(S)
   \
    o-G(G(S))

    hg log -r origin( G(S) )      # { S }
    hg log -r origin( G(G(S)) )   # { S }, NOT { G(S) }

Even if the last graft were a transplant

    hg log -r origin( T(G(S)) )   # { S }

A rebase without --keep essentially strips the source, so providing the cset
that results to this predicate will yield an empty set.

Note that the convert extension does not currently update the 'extra' map in
its destination csets, and therefore copies made prior to the convert will be
unable to find their source.
2012-07-07 00:47:30 -04:00
Pierre-Yves David
9e13d2931c obsolete: compute extinct changesets
`extinct` changesets are obsolete changesets with obsolete descendants only. They
are of no interest anymore and can be:

- exclude from exchange
- hidden to the user in most situation
- safely garbage collected

This changeset just allows mercurial to detect them.

The implementation is a bit naive, as for unstable changesets. We better use a
simple revset query and a cache, but simple version comes first.
2012-07-06 19:34:09 +02:00
Pierre-Yves David
2444c95546 obsolete: compute unstable changeset
An unstable changeset is a changeset *not* obsolete but with some obsolete
ancestors.

The current logic to decide if a changeset is unstable is naive and very
inefficient. A better solution is to compute the set of unstable changeset with
a simple revset and to cache the result. But this require cache invalidation
logic. Simpler version goes first.
2012-07-06 00:18:09 +02:00
Pierre-Yves David
940b30d287 revset: add an obsolete symbol
This predicate matches obsolete changesets.

This is a naive implementation to be improved later.
2012-07-06 19:29:10 +02:00
Angel Ezquerra
c386f40e4b revset: add "diff" field to "matching" keyword
The new "diff" field lets you use the matching revset keyword to find revisions
that apply the same change as the selected revisions.

The match must be exact (i.e. same additions, same deletions, same modified
lines and same change context, same file renames and copies).

Two revisions matching their diff must also match their files. Thus, to match
the diff much faster we will always check that the 'files' match first, and only
then check that the 'diff' matches as well.
2012-06-13 23:32:58 +02:00
Bryan O'Sullivan
513bd920fa revset: ensure we are reversing a list (issue3530) 2012-07-04 09:38:07 -07:00
Matt Harbison
524542016e revset: add a utility for obtaining the source of a given rev
graft, transplant and rebase all embed a different type of source marker in
extra, and each with a different name.  The current implementation of each is
such that there will never be more than one of these markers on a node.

Note that the rebase marker can only be resolved if the source is
still present, which excludes the typical rebase usage (without
--keep) from consideration (unless the resulting bundle in
strip-backup is overlayed). There probably isn't any reason to use
rebase --keep as a substitute for transplant or graft at this point,
but maybe there was at one point and there are even a few rebases in
the hg repo, so it may be of historical interest.
2012-06-05 20:35:34 -04:00
Matt Harbison
5c29c87aee revset: add a predicate for finding converted changesets
This selects changesets added because of repo conversions.  For example

    hg log -r "converted()"      # all csets created by a convertion
    hg log -r "converted(rev)"   # the cset converted from rev in the src repo

The converted(rev) form is analogous to remote(id), where the remote repo is
the source of the conversion.  This can be useful for cross referencing an old
repository into the current one.

The source revision may be the short changeset hash or the full hash from the
source repository.  The local identifier isn't useful.  An interesting
ramification of this is if a short revision is specified, it may cause more
than one changeset to be selected.  (e.g. converted(6) matches changesets with
a convert_revision field of 6e..e and 67..0)

The convert.hg.saverev option must have been specified when converting the hg
source repository for this to work.  The other sources automatically embed the
converted marker.
2012-05-13 01:12:26 -04:00
Bryan O'Sullivan
8585634f4d revset: introduce and use _revsbetween
This is similar in spirit to revlog.nodesbetween, but less ambitious,
much simpler, and ~2x faster.
2012-06-01 15:50:22 -07:00
Bryan O'Sullivan
609ea1623d revset: implement dagrange directly
This is much faster than the older implementation (~8x).
2012-06-01 15:50:22 -07:00
Bryan O'Sullivan
a5d8345282 revset: turn dagrange into a function 2012-06-01 15:50:22 -07:00
Bryan O'Sullivan
4fbcddec79 revset: drop unreachable code 2012-06-01 15:50:22 -07:00
Patrick Mezard
8870ba9d24 revset: cache alias expansions
Caching has no performance effect on the revset aliases which triggered
the recent recursive evaluation bug. I wrote it not to feel bad about
expanding several times the same complicated expression.
2012-05-24 13:05:06 +02:00
Bryan O'Sullivan
abdf4a8227 util: subclass deque for Python 2.4 backwards compatibility
It turns out that Python 2.4's deque type is lacking a remove method.
We can't implement remove in terms of find, because it doesn't have
find either.
2012-06-01 17:05:31 -07:00
Matt Mackall
acd12b376b revset: avoid validating all tag nodes for tag(x)
This generally causes the entire node->rev table to get built when
we're only interested in one node.
2012-06-01 15:13:05 -05:00
Simon King
099a5c925c revset: add pattern matching to 'extra' revset expression 2012-05-30 23:14:04 +01:00
Simon King
93954249b9 revset: add pattern matching to the 'user' revset expression 2012-05-30 23:13:58 +01:00
Simon King
e5e759a651 revset: add pattern matching to 'bookmarks' revset expression 2012-05-30 23:13:33 +01:00
Simon King
85110850a9 revset: add pattern matching to 'branch' revset expression 2012-05-30 23:13:33 +01:00
Simon King
9ecf845d55 revset: add pattern matching to 'tag' revset expression
If the string provided to the 'tag' predicate starts with 're:', the rest
of the string will be treated as a regular expression and matched against
all tags in the repository.

There is a slight backwards-compatibility problem for people who actually
have tags that start with 're:'. As a workaround, these tags can be matched
using a 'literal:' prefix.

If no tags match the pattern, an error is raised. This matches the behaviour
of the previous exact-match code.
2012-05-30 23:13:33 +01:00
Simon King
12ea13934c revset: add helper function for matching strings to patterns 2012-05-30 23:13:33 +01:00
Bryan O'Sullivan
bef5b61512 cleanup: use the deque type where appropriate
There have been quite a few places where we pop elements off the
front of a list.  This can turn O(n) algorithms into something more
like O(n**2).  Python has provided a deque type that can do this
efficiently since at least 2.4.

As an example of the difference a deque can make, it improves
perfancestors performance on a Linux repo from 0.50 seconds to 0.36.
2012-05-15 10:46:23 -07:00
Matt Mackall
8c3c80ff37 merge with stable 2012-05-22 14:37:20 -05:00
Patrick Mezard
139c15da66 revset: fix infinite alias expansion detection
The alias expansion code it changed from:
1- Get replacement tree
2- Substitute arguments in the replacement tree
3- Expand the replacement tree again

into:

1- Get the replacement tree
2- Expand the replacement tree
3- Expand the arguments
4- Substitute the expanded arguments in the replacement tree

and fixes cases like:

  [revsetalias]
  level1($1, $2) = $1 or $2
  level2($1, $2) = level1($2, $1)

  $ hg log -r "level2(level1(1, 2), 3)"

where the original version incorrectly aborted on infinite expansion
error, because it was confusing the expanded aliases with their
arguments.
2012-05-19 17:19:55 +02:00
Patrick Mezard
c7a80dee31 revset: explicitely tag alias arguments for expansion
The current revset alias expansion code works like:
1- Get the replacement tree
2- Substitute the variables in the replacement tree
3- Expand the replacement tree

It makes it easy to substitute alias arguments because the placeholders
are always replaced before the updated replacement tree is expanded
again. Unfortunately, to fix other alias expansion issues, we need to
reorder the sequence and delay the argument substitution. To solve this,
a new "virtual" construct called _aliasarg() is introduced and injected
when parsing the aliases definitions. Only _aliasarg() will be
substituted in the argument expansion phase instead of all regular
matching string. We also check user inputs do not contain unexpected
_aliasarg() instances to avoid argument injections.
2012-05-19 17:18:29 +02:00
FUJIWARA Katsunori
db8047a1c0 doc: add detail explanation for 'present()' predicate of revsets 2012-05-16 17:02:30 +09:00
Matt Harbison
353d5deeb2 revset: fix traceback for bogus revisions in id(rev)
hg log -r "id(1234567)" now returns an empty list like rev() does.
2012-05-14 19:25:13 -04:00
Matt Mackall
e0b2cc783f merge with stable 2012-05-20 14:40:36 -05:00
Matt Mackall
67c0680caa merge with stable 2012-05-17 15:52:14 -05:00
Brodie Rao
ab32f1721d context: add changectx.closesbranch() method
This removes the duplicated code for inspecting the 'close' extra field in
a changeset.
2012-05-13 14:04:06 +02:00
Brodie Rao
d6a6abf2b0 cleanup: eradicate long lines 2012-05-12 15:54:54 +02:00
Henrik Stuart
97ebbbffd1 revset: add function for matching extra data (issue2767) 2012-05-12 10:20:57 +02:00
Patrick Mezard
641ee7d3ba phases: introduce phasecache
The original motivation was changectx.phase() had special logic to
correctly lookup in repo._phaserev, including invalidating it when
necessary. And at other places, repo._phaserev was accessed directly.

This led to the discovery that phases state including _phaseroots,
_phaserev and _dirtyphase was manipulated in localrepository.py,
phases.py, repair.py, etc. phasecache helps encapsulating that.

This patch replaces all phase state in localrepo with phasecache and
adjust related code except for advance/retractboundary() in phases.
These still access to phasecache internals directly. This will be
addressed in a followup.
2012-05-12 00:24:07 +02:00
Bryan O'Sullivan
01cb9841ca bisect: track the current changeset (issue3382)
Introduce a new revset feature, bisect(current), that identifies
the changeset currently being bisected.
2012-05-08 15:29:09 -07:00
Patrick Mezard
1ecfe35e64 revset: make matching() preserve input revision order 2012-05-09 18:45:14 +02:00
Jesse Glick
33aa2b5c45 revset: documentation typo "metatadata" 2012-05-10 14:17:05 -04:00
FUJIWARA Katsunori
9fda466cef doc: flatten description of 'matching()' predicate to be formatted well
current description of 'matching()' revset predicate can't be
formatted well on "hg help revset" output.

each descriptions for revset predicates (or something like them) are
split-ed into lines, and spaces on left side of them are stripped
before minirst processing. so, bullet list can't be nested.

this patch just flattens description of 'matching()' predicate to be
formatted well.
2012-04-26 21:32:48 +09:00
Patrick Mezard
bed77ab945 revset: fix adds/modifies/removes and patterns (issue3403)
The fast path was triggered if the argument was not like "type:value", with
type a known pattern type. This is wrong for several reasons:
- path:value is valid for the fast path
- '*' is interpreted as a glob by default and is not valid for fast path

Fast path detection is now done after the pattern is parsed, and the normalized
path is extracted for direct comparison. All this seems a bit complicated, it
is tempting to drop the fast path completely. Also, the hasfile() revset does
something similar (only check .files()), without a fast path. If the fast path
is really that efficient maybe it should be used there too.

Note that:

  $ log 'modifies("set:modified()")'

is different from:

  $ log 'modifies("*")'

because of the usual merge ctx.files()/status(ctx.p1(), ctx) differences.

Reported by Steffen Eichenberg <steffen.eichenberg@msg-gillardon.de>
2012-04-26 14:24:46 +02:00
Bryan O'Sullivan
6dd793955c revset: fix O(n**2) behaviour of bisect() (issue3381) 2012-04-18 21:27:35 -07:00
Patrick Mezard
c57d92d67c revset: make matching() work on python 2.4
tuple.index() was apparently added to python 2.6:

  http://bugs.python.org/issue1696444

Also remove a trailing comma to make check-code.py happy.
2012-04-17 10:33:47 +02:00
Thomas Arendsen Hein
69b89489ab revset: use list instead of tuple for compatibility with python before 2.6
'string elements'.split() instead of explicitly typing a list of strings is
used. This is done in other parts of Mercurial code, too.
2012-04-17 15:10:33 +02:00
Angel Ezquerra
19cbf3a030 revset: speedup matching() by first matching fields that take less time to
match

This patch sorts the fields that are passed to the matching function so that it
always starts by matching those fields that take less time to match.

Not all fields take the same amount of time to match. I've done several
measurements running the following command:

hg --time log -r "matching(1, field)"

on the mercurial repository, and where 'field' was each one of the fields
accepted by match. In order to avoid the print overhead (which could be
different for different fields, given the different number of matches) I used a
modified version of the matching() function which always returns no matches.

These tests showed that different fields take wildly different amounts of time
to match. Particulary the substate field takes up to 25 seconds to match on my
machine, compared to the 0.3 seconds that takes to match the phase field or the
2 seconds (approx) that takes to match most fields. With this patch, matching
both the phase and the substate of a revision takes the same amount of time as
matching the phase.

The field match order introduced by this patch is as follows:

phase, parents, user, date, branch, summary, files, description, substate

An extra nice thing about this patch is that it makes the match time stable.
2012-04-14 01:41:03 +02:00
Angel Ezquerra
2b1f5fd344 revset: speedup matching() by stopping the match early if a field does not match
Rather than getting all the fields that are being matches from every revision
and then comparing them to those of the target revision, compare each field one
by one and stop the match as soon as there is a match failure.

This can greatly reduce the match time when matching multiple fields.
The impact on match time when matching a single field seems negligible
(according to my measurements).
2012-04-13 13:46:49 +02:00
Angel Ezquerra
806c38f88b revset: make matching keyword not match summary when matching for description 2012-04-13 13:35:45 +02:00
Matt Mackall
265f182101 revset: avoid demandimport bug
Apparently the "import x as xy" doesn't manage to update xy in the
current scope's dictionary after load, which causes nodemod.nullrev to do a huge amount of demandload magic in the inner loop.
2012-04-13 15:32:49 -05:00
Matt Mackall
af300e88ec merge with stable 2012-04-12 20:52:39 -05:00
Patrick Mezard
00224d1ac6 graphlog: correctly handle calls in subdirectories 2012-04-11 11:32:00 +02:00
Patrick Mezard
a07861a2e3 graphlog: fix --follow-first --rev combinations
This solves a similar problem than the previous --follow/--rev patch. This time
we need changelog.ancestors()/descendants() filtering on first parent.
Duplicating the code looked better than introducing keyword arguments. Besides,
the ancestors() version was already implemented in follow() revset.
2012-04-11 11:25:34 +02:00
Patrick Mezard
ef43384e07 revset: avoid set duplication in roots() 2012-04-08 11:14:56 +02:00
Patrick Mezard
af77d0083f revset: retrieve a bit less parents in roots() 2012-04-08 11:13:06 +02:00
Patrick Mezard
4bfe090298 revset: do not ignore input revisions in roots()
0233b606220f is also partially reverted to use the 'narrow' parameter again and
make less changesets parents lookups.
2012-04-08 11:11:30 +02:00
Angel Ezquerra
bfc07420f3 revset: add "matching" keyword
This keyword can be used to find revisions that "match" one or more fields of a
given set of revisions.

A revision matches another if all the selected fields (description, author,
branch, date, files, phase, parents, substate, user, summary and/or metadata)
match the corresponding values of those fields on the source revision.

By default this keyword looks for revisions that whose metadata match
(description, author and date) making it ideal to look for duplicate revisions.

matching takes 2 arguments (the second being optional):

1.- rev: a revset represeting a _single_ revision (e.g. tip, ., p1(.), etc)
2.- [field(s) to match]: an optional string containing the field or fields
(separated by spaces) to match.
    Valid fields are most regular context fields and some special fields:
    * regular fields:
      - description, author, branch, date, files, phase, parents,
      substate, user.
      Note that author and user are synonyms.
    * special fields: summary, metadata.
      - summary: matches the first line of the description.
      - metatadata: It is equivalent to matching 'description user date'
        (i.e. it matches the main metadata fields).

Examples:

1.- Look for revisions with the same metadata (author, description and date)
as the 11th revision:

hg log -r "matching(11)"

2.- Look for revisions with the same description as the 11th revision:

hg log -r "matching(11, description)"

3.- Look for revisions with the same 'summary' (i.e. same first line on their
description) as the 11th revision:

hg log -r "matching(11, summary)"

4.- Look for revisions with the same author as the current revision:

hg log -r "matching(., author)"

You could use 'user' rather than 'author' to get the same result.

5.- Look for revisions with the same description _AND_ author as the tip of the
repository:

hg log -r "matching(tip, 'author description')"

6.- Look for revisions touching the same files as the parent of the tip of the
repository

hg log -r "matching(p1(tip), files)"

7.- Look for revisions whose subrepos are on the same state as the tip of the
repository or its parent

hg log -r "matching(p1(tip):tip, substate)"

8.- Look for revisions whose author and subrepo states both match those of any
of the revisions on the stable branch:

hg log -r "matching(branch(stable), 'author substate')"
2012-04-01 14:12:14 +02:00
Patrick Mezard
e329a7b4ce debugrevspec: pretty print output
Before:

  ('func', ('symbol', 'reverse'), ('func', ('symbol', 'sort'), ('list', ('or',
  ('symbol', '2'), ('symbol', '3')), ('symbol', 'date'))))

After:

  (func
    ('symbol', 'reverse')
    (func
      ('symbol', 'sort')
      (list
        (or
          ('symbol', '2')
          ('symbol', '3'))
        ('symbol', 'date'))))

v2:
- Rebased on stable to avoid having to merge tests output
2012-02-24 11:02:21 +01:00
Patrick Mezard
57671f9108 context: add followfirst arg to filectx and workingfilectx
When _followfirst() revset was introduced it seemed to be the sole user of such
an argument, so filectx.ancestors() was duplicated and modified instead. It now
appears this argument could be used when computing the set of files to be
considered when --patch or --stat are passed along with --follow FILE.
2012-02-26 17:10:57 +01:00
Patrick Mezard
14c70f7752 graphlog: evaluate FILE/-I/-X filesets on the working dir
This subtlety is not documented yet but:
- pats/--include/--exclude filesets are evaluated against the working directory
- --rev filesets are reevaluated against every revisions
2012-02-26 17:10:51 +01:00
Patrick Mezard
38c46923b9 graphlog: implement --follow-first
log --graph --follow-first FILE cannot be compared with the regular version
because it never worked: --follow-first is not taken in account in
walkchangerevs() fast path and is explicitely bypassed in FILE case in
walkchangerevs() nested iterate() function.
2012-02-25 22:11:36 +01:00
Patrick Mezard
4dca114aca graphlog: paths/-I/-X handling requires a new revset
The filtering logic of match objects cannot be reproduced with the existing
revsets as it operates at changeset files level. A changeset touching "a" and
"b" is matched by "-I a -X b" but not by "file(a) and not file(b)".

To solve this, a new internal "_matchfiles(...)" revset is introduced. It works
like "file(x)" but accepts more than one argument and its arguments are
prefixed with "p:", "i:" and "x:" to be used as patterns, include patterns or
exclude patterns respectively.

The _matchfiles revset is kept private for now:
- There are probably smarter ways to pass the arguments in a user-friendly way
- A "rev:" argument is likely appear at some point to emulate log command
  behaviour with regard to filesets: they are evaluated for the parent revision
  and applied everywhere instead of being reevaluated for each revision.
2012-02-23 18:05:20 +01:00
FUJIWARA Katsunori
8e9263abed revset: fix documentation for 'remote()' predicate
current documentation for 'remote()' predicate is wrong about
specification of parameters.

there are 3 patterns:

  # of
  param:  id:              remote:
  - 0     current branch   "defult" remote
  - 1     specified        "defult" remote
  - 2     specified        specified
2012-01-27 22:29:58 +09:00
FUJIWARA Katsunori
fa22f7f531 revset: fix 'remote()' failure when remote repo has more revs than local
current 'remote()' implementation uses 'r' variable, even if it is not
initialized when 'if n in repo' is not true.

this causes unexpected exception.
2012-01-27 22:29:58 +09:00
Patrick Mezard
231c7be7bb revset: fix alias substitution recursion (issue3240)
The revset aliases expansion worked like:

  expr = "some revset"
  for alias in aliases:
      expr = alias.process(expr)

where "process" was replacing the alias with its *unexpanded* substitution,
recursively. So it only worked when aliases were applied in proper dependency
order.

This patch rewrites the expansion process so all aliases are expanded
recursively at every tree level, after parent alias rewriting and variable
expansion.
2012-02-09 21:03:07 +01:00
Matt Mackall
87fbd9f786 revset: include the correct first ancestor change for follow(file)
Previously we always included '.', which may not touch a file.
Instead, find the file revision present in '.' and add its linkrev.
This matches the results of 'hg log --follow file'.
2012-01-20 23:52:31 -06:00
Matt Mackall
0a56dd5a65 revset: remove unreferenced followfile function 2012-01-20 23:10:13 -06:00
Matt Mackall
8524d0bc06 revsets: provide contexts for filesets
Before this change, revsets containing fileset patterns failed. This
allows queries like:

 hg log -r "contains('set: added() and symlink()')"
2012-01-20 23:05:04 -06:00
Matt Mackall
7eeb2f277f revset: allow slashes in symbols
suggested by Ryan Kelly
2012-01-20 14:18:51 -06:00
Wagner Bruna
4d98f252a4 revset: fix typo in message 2012-01-20 13:19:39 -02:00
Matt Mackall
06e236e8f8 revset: add remote() predicate to lookup remote revisions 2012-01-19 14:31:05 -06:00
Matt Mackall
d2ef9d821b revset: roots needs to be computed on full set 2012-01-17 17:48:59 -06:00
Matt Mackall
f3e58790bb revset: optimize roots and children 2012-01-16 01:21:30 -06:00
Matt Mackall
0c33089f33 revset: optimize building large lists in formatrevspec
The large or-expressions we used to build required a substantial
amount of subset filtering in orset() which was inefficient. Instead we build a
single string which we process in one go with a special internal predicate.
2012-01-16 01:21:22 -06:00
Pierre-Yves David
e929cd5e49 discovery: introduce outgoing object for result of findcommonoutgoing
Simplifies client logic in multiple places since it encapsulates the
computation of the common and, more importantly, the missing node lists.

This also allows an upcomping patch to communicate precomputed versions of
these lists to clients.
2012-01-09 03:47:16 +01:00
Pierre-Yves David
b6988087ea phases: implements simple revset symbol
This changeset adds ``public()``, ``draft()`` and ``secret`` symbol for
revset.
2012-01-06 10:04:20 +01:00
Martin Geisler
ba8731035e Use explicit integer division
Found by running the test suite with the -3 flag to show places where
we have int / int division that can be replaced with int // int.
2012-01-08 18:15:54 +01:00
FUJIWARA Katsunori
09db6940ae i18n: use "encoding.lower()" to normalize specified string for revset
some problematic encoding (e.g.: cp932) uses ASCII alphabet characters
in byte sequence of multi byte characters.

"str.lower()" on such byte sequence may treat distinct characters as
same one, and cause unexpected log matching.

this patch uses "encoding.lower()" instead of "str.lower()" to
normalize strings for compare.
2011-12-25 20:35:16 +09:00
Matt Mackall
a224af5d42 merge with stable 2011-12-01 01:42:03 -06:00
Matt Mackall
a837de171f revset: balance %l or-expressions (issue3129) 2011-11-30 22:43:24 -06:00
Matt Mackall
8de0c77dee revset: follow(nosuchfile) should give an empty set (issue3114) 2011-11-20 15:29:55 -06:00
Pierre-Yves David
4d3328f835 revset: disambiguous the node variable
The module could be confused with the function.
2011-10-21 14:15:58 +02:00
Matt Mackall
01c8789013 revset: deal with empty lists in formatspec 2011-10-21 12:12:21 -05:00
Matt Mackall
2ba9ce4879 revset: fix %r handling in formatspec 2011-10-15 12:52:43 -05:00
Matt Mackall
275981abb2 revset: add %r for embedded revset support to formatspec
This allows folding external revsets or lists of revsets into a revset
expression. Revsets are pre-parsed for validity so that syntax errors
don't escape.
2011-10-15 10:20:08 -05:00
Yann E. MORIN
c5cb886778 hbisect: add two new revset descriptions: 'goods' and 'bads'
This patch adds two new revset descriptions:
 - 'goods': the list of topologicaly-good csets:
   - if good csets are topologically before bad csets, yields '::good'
   - else, yields 'good::'
 - and conversely for 'bads'

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
2011-09-24 01:32:50 +02:00
Yann E. MORIN
bd0d47a8d1 revset.bisect: add 'ignored' set to the bisect keyword
The 'ignored' changesets are outside the bisection range, but are
changesets that may have an impact on the outcome of the bisection.

For example, in case there's a merge between the good and bad csets,
but the branch-point is out of the bisection range, and the issue
originates from this branch, the branch will not be visited by bisect
and bisect will find that the culprit cset is the merge.

So, the 'ignored' set is equivalent to:
    (   ( ::bisect(bad) - ::bisect(good) )
      | ( ::bisect(good) - ::bisect(bad) ) )
    - bisect(range)

 - all ancestors of bad csets that are not ancestors of good csets, or
 - all ancestors of good csets that are not ancestors of bad csets
 - but that are not in the bisection range.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
2011-09-20 20:21:04 +02:00
Yann E. MORIN
67456b9f23 hbisect.get: use simpler code with repo.set(), fix 'pruned' set
Use repo.set() wherever possible, instead of locally trying to
reproduce complex graph computations.

'pruned' now means 'all csets that will no longer be visited by the
bisection'. The change is done is this very patch instead of its own
dedicated one becasue the code changes all over the place, and the
previous 'pruned' code was totally rewritten by the cleanup, so it
was easier to just change the behavior at the same time.

The previous series went in too fast for this cleanup pass to be
included, so here it is. ;-)

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
2011-09-20 20:19:48 +02:00
Matt Mackall
56d176a266 revset: add 'l' flag to formatspec for args
This makes it easy to calculate a revset with lists:

  good = [1, 2, 3]
  bad = [10, 11, 12]
  between = repo.set('%ld::%ld', good, bad)
2011-09-19 16:28:44 -05:00
Yann E. MORIN
bc668406c8 revset.bisect: add new 'untested' set to the bisect keyword
The 'untested' set is made of changesets that are in the bisection range
but for which the status is still unknown, and that can later be used to
further decide on the bisection outcome.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
2011-09-17 14:33:20 +02:00
Yann E. MORIN
414f1cadec revset.bisect: add new 'pruned' set to the bisect keyword
The 'pruned' set is made of changesets that did participate to
the bisection. They are made of
 - all good changesets
 - all bad changsets
 - all skipped changesets, provided they are in the bisection range

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
2011-09-17 17:30:35 +02:00
Yann E. MORIN
fdcfe85b83 revset.bisect: add new 'range' set to the bisect keyword
The 'range' set is made of all changesets that make the bisection
range, that is
 - csets that are ancestors of bad csets and descendants of good csets
 or
 - csets that are ancestors of good csets and descendants of bad csets

That is, roughly equivalent of:
  bisect(good)::bisect(bad) | bisect(bad)::bisect(good)

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
2011-09-17 17:33:34 +02:00
Yann E. MORIN
0223cbb500 revset.bisect: move bisect() code to hbisect.py
Computing the ranges of csets in the bisection belongs to the hbisect
code. This allows for reusing the status computation from many places,
not only the revset code, but also to later display the bisection status
of a cset...

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
2011-09-17 00:20:45 +02:00
Yann E. MORIN
0380741552 revset: rename bisected() to bisect()
Rename the 'bisected' keyword to simply 'bisect'.
Still accept the old name, but no longer advertise it.

As discussed with Matt on IRC.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
2011-09-18 22:54:11 +02:00
Yann E. MORIN
944c91d0c2 revset.bisected: remove 'unknown' state
'unknown' is not a valid bisect state, so causes a traceback.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
2011-09-18 10:07:51 +02:00
Matt Mackall
9af29ec474 revsets: add first alias for last 2011-09-17 12:34:47 -05:00
Matt Mackall
708a429360 revset: add default of 1 to limit and last functions 2011-09-16 22:57:47 -05:00
Matt Mackall
005a60af31 revset: add formatspec convenience query builder 2011-07-21 14:05:45 -05:00
Matt Mackall
870a9eda45 revset: allow bypassing alias expansion
For internal usage of revset queries, we don't want aliases breaking things.
2011-07-21 14:04:57 -05:00
Matt Mackall
47766aa6d3 revsets: actually catch type error on tip^p1(tip) (issue2884)
The previous commit was empty.
2011-07-12 12:35:03 -05:00
Matt Mackall
73b047e45e revsets: do the right thing with x^:y (issue2884)
Given an operator ^ that's either postfix or infix and an operator :
that's either prefix or infix, the parser can't figure out the right
thing to do. So we rewrite the expression to be sensible in the optimizer.
2011-07-06 13:37:50 -05:00
Mads Kiilerich
ed0023acf6 revset: fix aliases with 0 or more than 2 parameters
The existing code seemed to have incorrect assumptions about how parameter
lists are represented by the parser.

Now the match and replace functions have been merged and simplified by using
getlist().
2011-06-22 01:55:00 +02:00
Mads Kiilerich
7cf147b1a4 revset and fileset: fix typos in parser error messages 2011-06-22 01:55:00 +02:00
Mads Kiilerich
8ef684c2fc revset: fix parameter name in implementation of follow() 2011-06-24 00:18:06 +02:00
Mads Kiilerich
473bcd3ed1 parsers: fix localization markup of parser errors 2011-06-21 00:17:52 +02:00
Thomas Arendsen Hein
282b06cd6f revset: add desc(string) to search in commit messages
Like keyword(), but does not search in filenames and users.
No grepdesc() or descgrep() added, because it might be bad to introduce
grepfoo() versions of too many string searches.
2011-06-16 22:47:34 +02:00
Thomas Arendsen Hein
f770eadd10 revset: update sorting of symbols 2011-06-16 22:03:26 +02:00
Matt Mackall
efecb99535 hg: change various repository() users to use peer() where appropriate
This gets all the easy cases (peers that aren't also used as repositories).
2011-06-10 11:43:38 -05:00
Martin Geisler
9bc622d2ad merge with stable 2011-05-18 09:56:27 +02:00
Martin Geisler
9ea41d9e6c revset: the name is optional for the tag predicate 2011-05-18 09:31:19 +02:00
Martin Geisler
c9db075708 revset: note case-sensitive match in grep 2011-05-18 09:28:11 +02:00
Martin Geisler
009dc5d112 revset: note case-insensitive matches in keyword and user 2011-05-18 09:20:52 +02:00
Martin Geisler
e7ee99da82 revset: expand help for contains predicate 2011-05-18 09:15:18 +02:00
Matt Mackall
3974d4288a revset: add follow(filename) to follow a filename's history across copies 2011-05-16 17:02:35 -05:00
Matt Mackall
01a4d248e5 revset: introduce filelog() to emulate log's fast path
filelog() only reports revisions present in the matching filelogs.
2011-05-16 17:02:35 -05:00
Matt Mackall
1d5abac148 help: consolidate topic hooks in help.py
This removes loops like cmdutil->revset->help->extensions->cmdutil and
simplifies the code.
2011-05-13 12:57:27 -05:00
Mads Kiilerich
25da754c3d revset: fix typo when assigning weight to reverse and limit 2011-02-24 00:47:49 +01:00
Matt Mackall
018d171646 bookmarks: move revset support to core 2011-02-10 13:46:28 -06:00
Martin Geisler
6a3d9310ab code style: prefer 'is' and 'is not' tests with singletons 2010-11-22 18:15:58 +01:00
Patrick Mezard
43a1583455 revset: remove unnecessary debug statement 2010-11-07 18:15:17 +01:00
Patrick Mezard
a6f7f2ff05 revset: fix p1, p2 and parents in dirstate case (60aa454e7734)
- Handle 'subset' argument
- Stop returning the null rev from p1 and parents, as in the non-dirstate case
- Order parents as in the non-dirstate case (ascending revs)
2010-11-07 18:14:42 +01:00
Kevin Bullock
e238d72ecb revsets: let parents() return parents of working dir
This patch makes the 'set' argument to revset function parents() optional.
Like p1() and p2(), if no argument is given, returns the parent(s) of the
working directory.

Morally equivalent to 'p1()+p2()', as expected.
2010-11-04 17:09:00 -05:00
Kevin Bullock
63e0b7b699 revsets: let p1() and p2() return parents of working dir
This patch makes the 'set' argument to revset functions p1() and p2()
optional. If no argument is given, p1() and p2() return the first or second
parent of the working directory.

If the working directory is not an in-progress merge (no 2nd parent), p2()
returns the empty set. For a checkout of the null changeset, both p1() and
p2() return the empty set.
2010-11-04 16:59:03 -05:00
Wagner Bruna
1981a0d6f6 revset: fix missing dot in docstring 2010-10-27 12:12:51 -02:00
Wagner Bruna
2bff625586 i18n: translate revset predicate docstrings 2010-10-26 23:51:01 -02:00
Patrick Mezard
3fd83b5b68 hggettext: handle i18nfunctions declaration for docstrings translations 2010-10-24 12:52:37 +02:00