Commit Graph

190 Commits

Author SHA1 Message Date
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