Commit Graph

95 Commits

Author SHA1 Message Date
Martin von Zweigbergk
6fab52669c bundle: add config option to include phases
This adds an experimental.bundle-phases config option to include phase
information in bundles. As with the recently added support for
bundling obsmarkers, the support for bundling phases is hidden behind
the config option until we decide to make a bundlespec v3 that
includes phases (and obsmarkers and ...).

We could perhaps use the listkeys format for this, but that's
considered obsolete according to Pierre-Yves. Instead, we introduce a
new "phase-heads" bundle part. The new part contains the phase heads
among the set of bundled revisions. It does not include those in
secret phase; any head in the bundle that is not mentioned in the
phase-heads part is assumed to be secret. As a special case, an empty
phase-heads part thus means that any changesets should be added in
secret phase. (If we ever add a fourth phase, we'll include secret in
the part and we'll add a version number.)

For now, phases are only included by "hg bundle", and not by
e.g. strip and rebase.
2017-06-22 10:10:02 -07:00
Martin von Zweigbergk
46713842b3 pushkey: use False/True for return values from push functions
It was particularly unclear in phases.pushphase() whether the 0/1
returned were the 0/1 for public/draft phase or for False/True
2017-06-12 16:35:57 -07:00
Gregory Szorc
8637678d4e phases: emit phases to pushkey protocol in deterministic order
An upcoming test will report exact bytes sent over the wire protocol.
Without this change, the ordering of phases listkey data is
non-deterministic.
2017-04-13 22:12:04 -07:00
Augie Fackler
f080be2c20 phases: explicitly evaluate list returned by map
On Python 3 map() returns a generator, which bool()s to true even if
it had an empty input set. Work around this by using list() on the
map() result.
2017-03-11 20:53:20 -05:00
Jun Wu
668afd1cbd phases: remove experimental.nativephaseskillswitch
The native code has been used for a long time. Therefore drop the
experimental config option.
2017-03-01 15:50:01 -08:00
FUJIWARA Katsunori
19bd0eec9f phases: check HG_PENDING strictly
Before this patch, checking HG_PENDING in phases.py might cause
unintentional reading unrelated 'phaseroots.pending' in, because it
just examines existence of HG_PENDING environment variable.

This patch uses txnutil.trypending() to check HG_PENDING strictly.

BTW, this patch may cause failure of bisect in the repository of
Mercurial itself, if examination at bisecting assumes that an external
hook can see all pending changes while nested transactions across
repositories.

This invisibility issue will be fixed by subsequent patch, which
allows HG_PENDING to refer multiple repositories.
2017-02-21 01:21:00 +09:00
Jun Wu
e24ce907e3 phases: add a getrevset method to phasecache
This is part of a refactoring that moves some phase query optimization from
revset.py to phases.py.

The motivation behind this was chg repo preloading - to make the obsstore
depend on less things (like the revset language). The refactoring also looks
good by itself - phasecache does not expose its private field "_phasesets"
via public methods and revset.py is accessing it in a hacky way.

This patch adds a "getrevset" method, which takes multiple phases and
returns a revset in an best-effort efficient way - for "public" phase, it
returns a lazy generatorset; for "draft" and "secret", it returns efficient
"baseset".
2017-02-17 22:49:05 -08:00
Pulkit Goyal
f1c1938039 py3: replace os.environ with encoding.environ (part 1 of 5)
os.environ is a dictionary which has string elements on Python 3. We have
encoding.environ which take care of all these things. This is the first patch
of 5 patch series which tend to replace the occurences of os.environ with
encoding.environ as using os.environ will result in unusual behaviour.
2016-12-18 01:34:41 +05:30
FUJIWARA Katsunori
37b26ec7b6 phases: make writing phaseroots file out avoid ambiguity of file stat
Cached attribute repo._phasecache uses stat of '.hg/phaseroots' file
to examine validity of cached contents. If writing '.hg/phaseroots'
file out keeps ctime, mtime and size of it, change is overlooked, and
old contents cached before change isn't invalidated as expected.

To avoid ambiguity of file stat, this patch writes '.hg/phaseroots'
file out with checkambig=True.

This patch is a part of "Exact Cache Validation Plan":

    https://www.mercurial-scm.org/wiki/ExactCacheValidationPlan
2016-06-03 00:44:20 +09:00
Gregory Szorc
8aac5286e7 phases: use constants for phase values
Magic numbers hinder readability.
2016-02-15 16:49:52 -08:00
Bryan O'Sullivan
fd04392cbc with: use context manager for transaction in pushphase 2016-01-15 13:14:49 -08:00
Bryan O'Sullivan
2c9c32a10b with: use context manager for lock in pushphase 2016-01-15 13:14:49 -08:00
Durham Goode
d0bab13283 phase: improve retractboundary perf
The existing retractboundary implementation computed the new boundary by walking
all descendants of all existing roots and computing the new roots. This is
O(commits since first root), which on long repos can be hundreds of thousands of
commits.

The new algorithm only updates roots that are greater than the new root
locations. For common operations like commit on a repo with the earliest root
several hundred thousand commits ago, this makes retractboundary go from
1 second to 0.008 seconds.

I tested it by running the test suite with both implementations and checking
that the root results were always the identical.

There was some discussion on IRC about the safety of this (i.e. what if the new
nodes are already part of the phase, etc).  I've looked into it and believe this
patch is safe:

1) The old existing code already filters the input nodes to only contain nodes
   that require retracting (i.e. we only make node X a new root if the old phase
   is less than the target phase), so there's no chance of us adding a
   unnecessary root to the phase (unless the input root is made unnecessary by
   another root in the same input, but see point #3).

2) Another way of thinking about this is:  the only way the new algorithm would
   be different from the old algorithm is if it added a root that is a
   descendant of an old root (since the old algorithm would've caught this in
   the big "roots(%ln::)".  At the beginning of the function, when we filter out
   roots that already meet the phase criteria, the *definition* of meeting the
   phase criteria is "not being a descendant of an existing root".  Therefore,
   by definition none of the new roots we are processing are descendants of an
   existing root.

3) If two nodes are passed in as input, and one node is an ancestor of the other
   (and therefore the later node should not be a root), this is still caught by
   the 'roots(%ln::)' revset. So there's no chance of an extra root being
   introduced that way either.
2015-11-07 16:11:49 -08:00
Pierre-Yves David
30913031d4 error: get Abort from 'error' instead of 'util'
The home of 'Abort' is 'error' not 'util' however, a lot of code seems to be
confused about that and gives all the credit to 'util' instead of the
hardworking 'error'. In a spirit of equity, we break the cycle of injustice and
give back to 'error' the respect it deserves. And screw that 'util' poser.

For great justice.
2015-10-08 12:55:45 -07:00
Gregory Szorc
7a6829d5ad phases: use absolute_import 2015-08-08 19:46:33 -07:00
Gregory Szorc
5380dea2a7 global: mass rewrite to use modern exception syntax
Python 2.6 introduced the "except type as instance" syntax, replacing
the "except type, instance" syntax that came before. Python 3 dropped
support for the latter syntax. Since we no longer support Python 2.4 or
2.5, we have no need to continue supporting the "except type, instance".

This patch mass rewrites the exception syntax to be Python 2.6+ and
Python 3 compatible.

This patch was produced by running `2to3 -f except -w -n .`.
2015-06-23 22:20:08 -07:00
Matt Mackall
e73d6537ab publishing: use new helper method 2015-06-18 15:34:22 -05:00
Pierre-Yves David
bc1afdedda phase: remove a 'for x in "foo bar".split()' idiom in phasecache.replace
I find this idiom fairly horrible.
2015-06-15 16:06:17 -07:00
Pierre-Yves David
9c488819f9 phase: document the replace method
This is a minor documentation update to answer a co-worker question.
2015-06-15 16:06:24 -07:00
Pierre-Yves David
32f3ec0b50 phase: rename getphaserevs to loadphaserevs
This function is:
- already loading the data in place,
- used once in the code.

So we drop the return value and change the name to make this obvious. We keep
the function public because we'll have to use it in revset.
2015-06-15 16:04:14 -07:00
Pierre-Yves David
17d4d70d6d phase: also overwrite phase's sets when replacing a phasecache
We need to copy this new attributes around too. This fix an issue where phases
data used by 'not public()' were not invalidated properly.
2015-06-15 16:08:22 -07:00
Pierre-Yves David
9f292fb23c phase: invalidate the phase's set cache alongside the revs
Invalidate was leaving set data around leading to possible bugs in revset.
2015-06-15 15:57:47 -07:00
Pierre-Yves David
49dfe34926 phase: also copy phase's sets when copying phase cache
We forgot to add such copy when we added the attributes.
2015-06-15 15:52:52 -07:00
Pierre-Yves David
d82568c62e phases: really fix native phase computation
For some reason (probably rebase issue, leprechaun or badly resolved .rej)
4d2ffbaf1d5d contains only half of the emailed patches and do not fix the bug.
This patch adds the other half and enable the sweet native computation for real.

As expected this provide massive speedup along the board.

revset #0: not public()
   plain         first
0) 0.011960      0.010523
1) 0.000465   3% 0.000492   4%

revset #1: (tip~1000::) - public()
   plain         first
0) 0.025700      0.025169
1) 0.002864  11% 0.001899   7%

revset #2: not public() and branch("default")
   plain         first
0) 0.022842      0.020863
1) 0.011418  49% 0.010948   52%

However, it has a less impact (even bad) on first result time in simple
situation.  This comes from the overhead of building the set and filtering it.
This is especially true on my Mercurial repository (used here) where about 1/3
of the changesets are non public and hidden. This could be mitigated by a
caching of the set and a better usage of smartset in '_notpublic'. (But this
won't happen in this patch because the win is massive everywhere else).

revset #0: not public()
   last
0) 0.000081
1) 0.000493 x6.1 <-- bad impact

revset #1: (tip~1000::) - public()
   last
0) 0.013966
1) 0.002737  19%

revset #2: not public() and branch("default")
   last
0) 0.011021
1) 0.011038

The effect mostly disappear when the number of non-public changesets is small
and/or the repo get bigger. Result for Mozilla central:

Mozilla

revset #0: not public()
   plain         first         last
0) 0.092787      0.084094      0.000080
1) 0.000054   0% 0.000083   0% 0.000083

revset #1: (tip~1000::) - public()
   plain         first         last
0) 0.215607      0.183996      0.124962
1) 0.031620  14% 0.006616   3% 0.031168  24%

revset #2: not public() and branch("default")
   plain         first         last
0) 0.092626      0.082687      0.000162
1) 0.000139   0% 0.000165   0% 0.000167
2015-06-10 19:26:16 -07:00
Laurent Charignon
3a3486745e phases: add set per phase in C phase computation
To speed up the computation of draft(), secret(), divergent(), obsolete() and
unstable() we need to have a fast way of getting the list of revisions that
are in draft(), secret() or the union of both: not public().

This patch extends the work on phase computation in C and make the phase
computation code also return a list of set for each non public phase.
Using these sets we can quickly obtain all the revisions of a given phase.
We do not return a set for the public phase as we expect it to be roughly the
size of the repo. Also, it can be computed easily by substracting the entries in the
non public phases from all the revs in the repo.
2015-04-01 11:17:17 -07:00
Laurent Charignon
a2ad3d1abd phases: make two functions private for phase computation 2015-03-30 15:38:24 -07:00
Laurent Charignon
9430b8ddec phases: add killswitch for native implementation 2015-03-30 12:57:55 -07:00
Laurent Charignon
5e18944310 phases: move pure phase computation in a function 2015-03-30 12:48:15 -07:00
Laurent Charignon
6b06793e68 phase: default to C implementation for phase computation 2015-03-20 11:14:27 -07:00
Angel Ezquerra
6e49f7def8 localrepo: remove all external users of localrepo.sopener
This change touches every module in which repository.sopener was being used, and
changes it for the equivalent repository.svfs.

It should now be possible to remove localrepo.sopener.
2015-01-11 00:25:54 +01:00
Eric Sumner
c8d74ee479 bundlerepo: implement safe phasecache
This patch makes bundlerepo use a subclass of phasecache that will allow phase
boundaries to be moved around, but will never write them to the underlying
repository.
2014-12-18 11:38:48 -08:00
Pierre-Yves David
160c394fe7 phases: read pending data when appropriate
If we are called by a hook and pending data exists, read those.
2014-10-17 22:23:06 -07:00
Pierre-Yves David
578b6cd317 phases: inform transaction-related hooks that a phase was moved
We do not have enough information to provide finer data, but this is still
useful information.
2014-10-12 08:03:20 -07:00
Durham Goode
030db2699f phases: move root phase assignment to it's own function
This moves the initial root phase assignment to it's own function. Future
patches which make phase calculations lazy will use this function to pre-fill
certain phases which can be deduced from the roots.
2014-10-07 11:42:37 -07:00
Durham Goode
0d0869f7ae phases: add invalidate function
Phase cache invalidation was spread all over the place. Let's add a function to
unify it. Later more will be added to this function.
2014-10-07 11:37:54 -07:00
Pierre-Yves David
db81cffcdc phase: attach phase to the transaction instead of the lock
The phase cache file is no longer written on lock release, it is now handled by
the transaction (as changesets and obsolescence markers are).

(Hooray)

As we stop relying on the lock to write phase, repos with no existing phase
information will need to wait for a phase move or a strip to happen in order to
get the first write in the `phaseroots` file. This explain the change in
test-inherit-mode.t.

This should not have any side effects but in very obscure cases where
people interact with pre-2.1 and post-2.1 versions of Mercurial on the
same repo while having MQ patches applied but the MQ extension
disabled from time to time. A case unlikely enough to not be worth
preserving the old behavior with awful hacks.
2014-08-07 14:11:36 -07:00
Pierre-Yves David
60e760ea53 phase: extract the phaseroots serialization in a dedicated method
In most case, the file creation logic will be handled by the
transaction itself. The write method has to stay around for the case
where the repository is modified outside a transaction (strip).
2014-08-07 14:41:00 -07:00
Pierre-Yves David
5f2b50474c phase: add a transaction argument to retractboundary
We now pass a transaction option to this phase movement function. The
object is currently not used by the function, but it will be in the
future.

All call sites have been updated. Most call sites were already enclosed in a
transaction for a long time. The handful of others have been recently
updated in previous commit.
2014-08-05 23:52:21 -07:00
Pierre-Yves David
a9275323db phase: add a transaction argument to advanceboundary
We now pass a transaction option to this phase movement function. The object
is currently not used by the function, but it will be in the future.

All call sites have been updated. Most call sites were already enclosed in a
transaction for a long time. The handful of others have been recently
updated in previous commit.

The retractboundary function remains to be upgraded.
2014-08-06 01:54:19 -07:00
Pierre-Yves David
4d38b093fd pushkey: wrap pushkey phase movement in a transaction
Phases are not yet inside the transaction, but we need to prepare for it. So we
wrap the phase movement inside a transaction.
2014-08-06 00:54:58 -07:00
Mads Kiilerich
02d72edf5e phases: make order of debug output 'removing unknown node' deterministic 2014-02-20 02:43:17 +01:00
Durham Goode
64d690fd9a rebase: fix rebase aborts when 'tip-1' is public (issue4082)
When aborting a rebase where tip-1 is public, rebase would fail to undo the merge
state. This caused unexpected dirstate parents and also caused unshelve to
become unabortable (since it uses rebase under the hood).

The problem was that rebase uses -2 as a marker rev, and when it checked for
immutableness during the abort, -2 got resolved to the second to last entry in
the phase cache.

Adds a test for the fix. Add exception to phase code to prevent this in the
future.
2013-11-04 19:59:00 -08:00
Mads Kiilerich
eabc047878 spelling: random spell checker fixes 2013-10-24 01:49:56 +08:00
Pierre-Yves David
c894d35e04 destroyed: invalidate phraserevs cache in all case (issue3858)
When revisions are destroyed, the `phaserevs` cache becomes invalid in most case.
This cache hold a `{rev => phase}` mapping and revision number most likely
changed.

Since cc14b89388cb, we filter unknown phases' roots after changesets
destruction.  When some roots are filtered the `phaserevs` cache is invalidated.
But not if none root where destroyed.

We now invalidate the cache in all case filtered root or not.

This bug was a bit tricky to reproduce as in most case we either:
* rebase a set a draft changeset including root (phaserev invalidated)
* strip tip-most changesets (no re-numbering of revision)

Note that the invalidation of `phaserevs` are not strictly needed when only
tip-most part of the history have been destroyed. But I do not expect the
overhead to be significant.
2013-04-15 17:10:58 +02:00
Idan Kamara
e3cd3c1a91 phases: make _filterunknown a member function of phasecache
We'd like the ability to call filterunknown on an existing phasecache
instance after nodes are destroyed.
2013-01-04 06:11:29 +01:00
Pierre-Yves David
e3f34c0ee1 cache: group obscache and revsfiltercache invalidation in a single function
Both caches are very volatile and needs invalidation on the same kind of event.
revsfiltercache actually depends on the content of revsfiltercache.
2012-12-18 02:04:37 +01:00
Pierre-Yves David
0ea6453a8a clfilter: add a cache on repo for set of revision to filter for a given set.
Recomputing the filtered revisions at every access to changelog is far too
expensive. This changeset introduce a cache for this information. This cache is
hold by the repository (unfiltered repository) and invalidated when necessary.
This cache is not a protected attribute (leading _) because some logic that
invalidate it is not held by the local repo itself.
2012-12-20 17:14:07 +01:00
Pierre-Yves David
fd66efd696 clfilter: phases logic should be unfiltered
Phase computations and boundary movements need to be aware of all
revisions that exist in the repository to return correct results.
2012-11-21 00:53:45 +01:00
André Sintzoff
94ef5e50d6 phases: fix missing "error" module import (issue3707) 2012-11-25 20:39:37 +01:00
Pierre-Yves David
5ae3830b30 clfilter: introduce a hassecret function
We can only use copy clone if the cloned repo do not have any secret changeset.
The current method for that is to run the "secret()" revset on the remote repo.
But with proper filtering of hidden or unserved revision by the remote this
revset won't return any revision even if some exist remotely. This changeset
adds an explicit function to know if a repo have any secret revision or not.

The other option would be to disable filtering for the query but I prefer the
approach above, lighter both regarding code and performance.
2012-09-03 14:05:19 +02:00