Commit Graph

57 Commits

Author SHA1 Message Date
Lucas Moscovicz
ef95629110 revset: extend sorting tests 2014-03-11 17:25:53 -07:00
Lucas Moscovicz
f3f67eb57f tests: added tests to test sort revset
This tests are intended to test sort in many different cases where it could
fail when using the new structures
2014-03-13 17:20:03 -07: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
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
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
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
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
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
Mads Kiilerich
7c13eeb821 commit: allow closing "non-head" changesets
Backout 308a153b9120. The changeset prevented closing non-head changesets but
did not provide any rationale or test case and I don't see what value it adds.
Users might have their reasons to commit something anywhere - and close it
immediately.

And contrary to the comment that is removed: The topo heads set is _not_
included in the branch heads set of the current branch. It do not include
closed topological heads.

The change thus prevented closing commits on top of closing commits. A valid
usecase for that is to merge closed heads to reduce the number of topological
heads.

The only existing test coverage for this is the failing double close in
test-revset.t. It was added in dc0e42c06b4e and seems to not be intentional.
2013-04-10 13:12:24 +02: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
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
FUJIWARA Katsunori
c9c2aa4085 test: add test for the issue introduced by 63af8381691a (issue3669)
63af8381691a (released as Mercurial 2.3) introduced the issue that the
revset program started with 40 hexadecimal letters caused unexpected
result at "hg log" execution.

This issue was already fixed by b579dcd15206 (released as 2.3.1), but
there is no test to examine whether this issue is certainly fixed or
not: no test fails even if b579dcd15206 is backed out.

This patch adds test for this issue.

Added test is also confirmed to fail, when it is tested against:

  - Mercurial 2.3, or
  - Mercurial 2.3.1 or later with backing b579dcd15206 out
2012-10-23 17:06:31 +09: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
Bryan O'Sullivan
513bd920fa revset: ensure we are reversing a list (issue3530) 2012-07-04 09:38:07 -07:00
Adrian Buehlmann
18c4705033 test-revset: enable for Windows
In MSYS, the test fails like this if the hghave exit at the beginning is
removed:

  --- C:\Users\adi\hgrepos\hg-main\tests\test-revset.t
  +++ C:\Users\adi\hgrepos\hg-main\tests\test-revset.t.err
  @@ -58,7 +58,7 @@
     $ hg co 3
     2 files updated, 0 files merged, 0 files removed, 0 files unresolved
     $ hg branch /a/b/c/
  -  marked working directory as branch /a/b/c/
  +  marked working directory as branch a:/b/c/
     (branches are permanent and global, did you want a bookmark?)
     $ hg ci -Aqm"5 bug"

  @@ -252,7 +252,7 @@
     2 a-b-c-
     3 +a+b+c+
     4 -a-b-c-
  -  5 /a/b/c/
  +  5 a:/b/c/
     6 _a_b_c_
     7 .a.b.c.
     $ log 'children(ancestor(4,5))'

due to the posix path conversion done by MSYS globally, as explained here

  http://www.mingw.org/wiki/Posix_path_conversion

The solution is a bit lame, but it is simple and works: don't use strings that
look like '/a/b', in order not to trigger the path magic done by MSYS.

So, if we can agree not to insist on testing branch names starting with '/',
then this relatively simple patch makes the test pass both on Windows with MSYS
and Linux.
2012-06-03 09:06:15 +02: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
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
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
Henrik Stuart
97ebbbffd1 revset: add function for matching extra data (issue2767) 2012-05-12 10:20:57 +02:00
Patrick Mezard
1ecfe35e64 revset: make matching() preserve input revision order 2012-05-09 18:45:14 +02: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
Angel Ezquerra
103460f1f9 tests: add tests for matching keyword
This adds a couple of tests for the revset "matching" keyword:

1. Test that the 2nd parameter is optional
2. Test that all the 1st argument can be a revset and that all the supported
fields of the 2nd argument work.
2012-04-15 00:27:31 +02: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
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
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
FUJIWARA Katsunori
96875b39e1 revset: add tests for 'remote()' predicate 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
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
a968007692 merge with stable 2011-12-08 16:01:44 -06:00
Matt Mackall
a69962e18c branch: warn on branching 2011-12-08 14:32:44 -06:00
Mads Kiilerich
c9c5f0a2ca tests: introduce 'hghave msys' to skip tests that would fail because of msys 2011-11-21 01:49:20 +01: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
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
Mads Kiilerich
6cadc46456 revset: avoid over-aggresive optimizations of non-filtering functions (issue2549)
When limit, last, min and max were evaluated they worked on a reduced set in the
wrong way. Now they work on an unrestricted set (the whole repo) and get
limited later on.
2011-05-01 17:35:05 +02:00
Alexander Solovyov
2f6ab6bf04 revset aliases 2011-04-30 18:30:14 +02:00
Kevin Gessner
9374e33026 revset: add tests for multiple and mixed ^ and ~ operators 2011-04-30 18:53:56 +02:00
Kevin Gessner
c6374d2d98 revset: add ^ and ~ operators from parentrevspec extension
^ (Nth parent) and ~ (Nth first ancestor) are infix operators that match
certain ancestors of the set:

  set^0
  the set

  set^1 (also available as set^)
  the first parent of every changeset in set

  set^2
  the second parent of every changeset in set

  set~0
  the set

  set~1
  the first ancestor (i.e. the first parent) of every changeset in set

  set~2
  the second ancestor (i.e. first parent of first parent) of every changeset
  in set

  set~N
  the Nth ancestor (following first parents only) of every changeset in set;
  set~N is equivalent to set^1^1..., with ^1 repeated N times.
2011-04-30 17:43:04 +02:00
Augie Fackler
52f8941398 revsets: preserve ordering with the or operator
This is valuable because now revsets like 'bookmarks() or tip' will
always show tip after bookmarks unless tip was itself a bookmark. This
is a somewhat contrived example, but this behavior is useful for
"where am I" type aliases that use log and revsets.
2011-04-13 12:30:41 -05:00
Idan Kamara
3828767e58 tests: add tests for non-existant branch/tag/bookmark 2011-04-10 11:30:53 +03:00
Bernhard Leiner
baf797018e revset: report a parse error if a revset is not parsed completely (issue2654) 2011-03-16 23:09:14 +01:00
Mads Kiilerich
635406bf76 tests: use (esc) for all non-ASCII test output 2010-11-08 01:41:41 +01:00
Wagner Bruna
d4398837df revset: disable subset optimization for parents() and children() (issue2437)
For the boolean operators, the subset optimization works by calculating
the cheaper argument first, and passing the subset to the second
argument to restrict the revision domain. This works well for filtering
predicates.

But parents() don't work like a filter: it may return revisions outside the
specified set. So, combining it with boolean operators may easily yield
incorrect results. For instance, for the following revision graph:

0 -- 1

the expression '0 and parents(1)' should evaluate as follows:

0 and parents(1) ->
0 and 0 ->
0

But since [0] is passed to parents() as a subset, we get instead:

0 and parents(1 and 0) ->
0 and parents([]) ->
0 and [] ->
[]

This also affects children(), p1() and p2(), for the same reasons.
Predicates that call these (like heads()) are also affected.

We work around this issue by ignoring the subset when propagating
the call inside those predicates.
2010-10-15 03:30:38 -03:00
Benoit Boissinot
d7dc2daaa0 revset: use 'requires' instead of 'wants' in error message 2010-10-16 18:50:53 +02:00
Augie Fackler
5fe5470142 revset: add id() and rev() to allow explicitly referring to changes by hash or rev 2010-10-11 09:44:19 -05:00