Commit Graph

228 Commits

Author SHA1 Message Date
Jun Wu
b99bc99ff6 bundle2: use ProgrammingError 2017-03-26 16:57:25 -07:00
Gregory Szorc
5ca0f908bf py3: add __bool__ to every class defining __nonzero__
__nonzero__ was renamed to __bool__ in Python 3. This patch simply
aliases __bool__ to __nonzero__ for every class implementing
__nonzero__.
2017-03-13 12:40:14 -07:00
Augie Fackler
d19fbe9c1b merge with stable 2017-02-15 11:22:01 -05:00
Siddharth Agarwal
7d1a6f9777 bundle2: fix assertion that 'compression' hasn't been set
`n.lower()` will return `compression`, not `Compression`.
2017-02-13 11:43:12 -08:00
Gregory Szorc
9efea3d15c bundle2: allow compression options to be passed to compressor
Compression engines allow options to be passed to them to control
behavior. This patch exposes an argument to bundle2.writebundle()
that passes options to the compression engine when writing compressed
bundles. The argument is honored for both bundle1 and bundle2, the
latter requiring a bit of plumbing to pass the value around.
2017-01-10 11:19:37 -08:00
Pierre-Yves David
683feeeddd bundle2: implement a basic __repr__ for bundle2 part
We display basic data as the part id and part type. This make debugging bundle2
related code friendlier.
2017-02-02 14:19:48 +01:00
Pierre-Yves David
24dbeff39a bundle2: drop an outdated comment
The function is no longer in "early" stage and have been used in production for
years. We can probably drop that part of the docstring...
2017-02-02 11:03:41 +01:00
Gregory Szorc
2e5ba752dd bundle2: equate 'UN' with no compression
An upcoming patch will change the "alg" argument passed to this
function from None to "UN" when no compression is wanted.

The existing implementation of bundle2 does not set a "Compression"
parameter if no compression is used. In theory, setting
"Compression=UN" should work. But I haven't audited the code to see if
all client versions supporting bundle2 will accept this.

Rather than take the risk, avoid the BC breakage and treat "UN"
the same as None.
2016-11-10 23:29:01 -08:00
Gregory Szorc
ddaa837b1a bundle2: use compressstream compression engine API
Compression engines now have an API for compressing a stream of
chunks. Switch to it and make low-level compression code disappear.
2016-11-07 18:46:37 -08:00
Gregory Szorc
e1a5352aa0 bundle2: use compression engines API to obtain decompressor
Like the recent change for the compressor side, this too is
relatively straightforward. We now store a compression engine
on the instance instead of a low-level decompressor. Again, this
will allow us to easily transition to different compression engine
APIs when they are implemented.
2016-11-07 18:36:48 -08:00
Gregory Szorc
1ddbc0cc5d bundle2: use new compression engine API for compression
Now that we have a new API to define compression engines, let's put it
to use!

The new code stores a reference to the compression engine instead of
a low-level compressor object. This will allow us to more easily
transition to different APIs on the compression engine interface
once we implement them.

As part of this, we change the registration in bundletypes to use 'UN'
instead of None. Previously, util.compressors had the no-op compressor
registered under both the 'UN' and None keys. Since we're switching to
a new API, I don't see the point in carrying this dual registration
forward.
2016-11-07 18:35:43 -08:00
Gregory Szorc
d694855e6f bundle2: only emit compressed chunks if they have data
This is similar to 72dcaa40df76. Not all calls into the compressor
return compressed data, as the compressor may buffer compressed
output internally. It is cheaper to check for empty chunks than to
send empty chunks through the generator.

When generating a gzip-v2 bundle of the mozilla-unified repo, this
change results in 50,093 empty chunks not being sent through the
generator (out of 1,902,996 total input chunks).
2016-10-15 17:10:53 -07:00
Yuya Nishihara
7c03e0d6ba pycompat: provide 'ispy3' constant
We compare version_info at several places, which seems enough to define
a constant.
2016-09-28 20:01:23 +09:00
Pierre-Yves David
5bcff70a60 merge with stable 2016-09-14 17:12:39 +02:00
Akihiko Odaki
82bf519632 bundle2: localize handleoutput remote prompts
Code archaeology suggests that there was no good reason for this not to
be localized. 'remote: ' is already localized elsewhere.
2016-09-01 13:16:55 -05:00
Gregory Szorc
c48909f844 bundle2: fail faster when interrupted
Before this patch, bundle2 application attempted to consume remaining
bundle2 part data when the process is interrupted (SIGINT) or when
sys.exit is called (translated into a SystemExit exception). This
meant that if one of these occurred when applying a say 1 GB
changegroup bundle2 part being downloaded over a network, it may take
Mercurial *several minutes* to terminate after a SIGINT because the
process is waiting on the network to stream megabytes of data. This is
not a great user experience and a regression from bundle1. Furthermore,
many process supervisors tend to only give processes a finite amount of
time to exit after delivering SIGINT: if processes take too long to
self-terminate, a SIGKILL is issued and Mercurial has no opportunity to
clean up. This would mean orphaned locks and transactions. Not good.

This patch changes the bundle2 application behavior to fail faster
when an interrupt or system exit is requested. It does so by not
catching BaseException (which includes KeyboardInterrupt and
SystemExit) and by explicitly checking for these conditions in
yet another handler which would also seek to the end of the current
bundle2 part on failure.

The end result of this patch is that SIGINT is now reacted to
significantly faster: the active transaction is rolled back
immediately without waiting for incoming bundle2 data to be consumed.
This restores the pre-bundle2 behavior and makes Mercurial treat
signals with the urgency they deserve.
2016-08-25 19:53:14 -07:00
Gregory Szorc
4ad5f2e492 bundle2: store changeset count when creating file bundles
The bundle2 changegroup part has an advisory param saying how many
changesets are in the part. Before this patch, we were setting
this part when generating bundle2 parts via the wire protocol but
not when generating local bundle2 files.

A side effect of not setting the changeset count part is that progress
bars don't work when applying changesets. As the tests show, this
impacted clone bundles, shelve, backup bundles, `hg unbundle`, and
anything touching bundle2 files.

This patch adds a backdoor to allow us to pass state from
changegroup generation into the unbundler. We store the number
of changesets in the changegroup in this state and use it to
populate the aforementioned advisory part parameter when generating
the bundle2 bundle.

I concede that I'm not thrilled by how state is being passed in
changegroup.py (it feels a bit hacky). I would love to overhaul the
rather confusing set of functions in changegroup.py with something that
passes rich objects around instead of e.g. low-level generators.
However, given the code freeze for 3.9 is imminent, I'd rather not
undertake this endeavor right now. This feels like the easiest way
to get the parameter added to the changegroup part.
2016-07-17 15:13:51 -07:00
Gregory Szorc
71e33a969a bundle2: use a sorted dict for holding parameters
An upcoming change that introduces a 2nd part parameter to a part
reveals that `hg debugbundle` isn't deterministic because parameters
are stored on n plain, unsorted dict.

While we could change that command to sort before output, I think
the more important underlying issue is that bundle2 reading is taking
an ordered data structure and converting it to an unordered one.
Plugging in util.sortdict() fixes that problem while preserving API
compatibility.

This patch also appears to shine light on the fact that we don't
have tests verifying parts with multiple parameters roundtrip
correctly. That would be a good thing to test (and fuzz)... someday.
2016-07-17 14:51:00 -07:00
Mads Kiilerich
f1004d7ba4 bundle2: don't assume ordering of heads checked after push
Usually, the heads will have the same ordering in handlecheckheads. Insisting
on the same ordering is however an unnecessary constraint that in some custom
cases can cause pushes to fail even though the actual heads didn't change. This
caused production issues for us in combination with the current version of
https://bitbucket.org/Unity-Technologies/hgwebcachingproxy/ .
2016-06-01 21:40:52 +02:00
Pulkit Goyal
9d5cc65520 py3: conditionalize the raise statement
raise E,V,T is not acceptable in Python 3, thats is conditionalized.
Moreover this will result in syntax error so we have to use exec() to
execute this. Related PEP- https://www.python.org/dev/peps/pep-3109/#id14

My implementation is motivated from the six implementation except they are
defining a new function exec_() to prevent adding an extra frame AFAIK :)

https://bitbucket.org/gutworth/six/src/ca4580a5a648/six.py#six.py-680
2016-08-08 23:51:11 +05:30
timeless
109fcbc79e pycompat: switch to util.urlreq/util.urlerr for py3 compat 2016-04-06 23:22:12 +00:00
Martin von Zweigbergk
d613237780 bundle: remove obsolete (and duplicate) comment
Change 760f9c8ad835 (changegroup: move chunk extraction into a
getchunks method of unbundle10, 2014-04-10) extracted some code to a
getchunks() method and copied a comment about the changegroup format
to the new method. The copy that remains in the old place, doesn't
make much sense there, so let's remove it.
2016-03-29 10:21:05 -07:00
Martin von Zweigbergk
4cc86f7b27 bundle: move writebundle() from changegroup.py to bundle2.py (API)
writebundle() writes a bundle2 bundle or a plain changegroup1. Imagine
away the "2" in "bundle2.py" for a moment and this change should makes
sense. The bundle wraps the changegroup, so it makes sense that it
knows about it. Another sign that this is correct is that the delayed
import of bundle2 in changegroup goes away.

I'll leave it for another time to remove the "2" in "bundle2.py"
(alternatively, extract a new bundle.py from it).
2016-03-28 14:41:29 -07:00
Martin von Zweigbergk
86ca76bafe changegroup: fix pulling to treemanifest repo from flat repo (issue5066)
In b89de5ee5b31 (changegroup: don't support versions 01 and 02 with
treemanifests, 2016-01-19), I stopped supporting use of cg1 and cg2
with treemanifest repos. What I had not considered was that it's
perfectly safe to pull *to* a treemanifest repo using any changegroup
version. As reported in issue5066, I therefore broke pull from old
repos into a treemanifest repo. It was not covered by the test case,
because that pulled from a local repo while enabling treemanifests,
which enabled treemanifests on the source repo as well. After
switching to pulling via HTTP, it breaks.

Fix by splitting up changegroup.supportedversions() into
supportedincomingversions() and supportedoutgoingversions().
2016-01-27 09:07:28 -08:00
Augie Fackler
54446bb7e0 cleanup: use modern @property/@foo.setter property specification
We can use this now that we're 2.6+, and this is more idiomatic modern
Python.
2016-01-16 10:50:28 -05:00
Martin von Zweigbergk
e5bd6473b3 changegroup: hide packermap behind methods
This is to prepare for hiding changegroup3 behind a config option.
2016-01-12 21:01:06 -08:00
Martin von Zweigbergk
417363259e treemanifests: set bundle2 part parameter indicating treemanifest
By adding a mandatory 'treemanifest' parameter in the bundle2 part, we
make it possible for the recipient to set repo requirements before the
manifest revlog is accessed.
2016-01-08 21:13:06 -08:00
Gregory Szorc
059667a51c bundle2: attribute remote failures to remote (issue4788)
Before bundle2, hook output from hook failures was prefixed with
"remote: ". Up to this point with bundle2, the output was converted to
the message to print in an Abort exception. This had 2 implications:

1) It was unclear whether an error message came from the local repo
   or the remote
2) The exit code changed from 1 to 255

This patch changes the handling of error:abort bundle2 parts during push
to prefix the error message with "remote: ". This restores the old
behavior.

We still preserve the behavior of raising an Abort during bundle2
application failure. This is a regression from pre-bundle2 because the
exit code changed.

Because we no longer raise an Abort with the remote's message, we needed
to insert a message for the new Abort. So, I invented a new error
message for that. This is another change from pre-bundle2. However, I
like the new error message because it states unambiguously who aborted
the push failed, which I think is important for users so they can decide
what's next.
2015-10-24 00:39:22 +01:00
Pierre-Yves David
2468be2e78 bundle2: make unbundle.compressed return True when compressed
We were returning 'False' in all cases, even when the bundle2 was actually
compressed.
2015-10-02 23:21:39 -07:00
Pierre-Yves David
fb85c76c3c applybundle: take url as argument
We allow specifying the url to carry it to hooks. This gets us closer to
'bundle1.apply(...)' and will allow us to remove regressions in multiple place
where we forget to pass the url to hooks.
2015-10-20 15:55:04 +02:00
Pierre-Yves David
737d464351 applybundle: take source as argument
We allow specifying the source to carry it to hooks. This gets us closer to
'bundle1.apply(...)' and will allow us to remove regressions in multiple places
where we forget to pass the source to hooks.
2015-10-20 15:52:42 +02:00
Pierre-Yves David
a8f2963ec8 applybundle: set 'bundle2=1' env for all transaction
This should be set for all bundle2 application, we enforce that at a low level.
This is for courtesy with hooks.
2015-10-20 15:48:24 +02:00
Pierre-Yves David
bffc6ff104 bundle2: introduce an "applybundle" function
There is a case where the intent is clear and the transaction is not optional. We
want to be able to alter that transaction in a wide and easy way. We cannot get
a unified '.apply(repo)' method for bundle1 and bundle2 yet because the api are
still a bit too far apart. But this is a good step forward to get the rc out.
2015-10-20 15:45:39 +02:00
Augie Fackler
b9b5df0ea1 bundle2: use cg?unpacker.apply() instead of changegroup.addchangegroup() 2015-10-13 17:11:52 -04:00
Pierre-Yves David
e5984e269f bundle2: gracefully skip 'obsmarkers' part if evolution is disabled
We would skip the part if it was fully unknown, so we should also skip it if we
know we won't be able to apply it. This will allow us to produce bundles with
obsolescence markers alongside changegroup while still being able to apply them
on any client.
2015-10-15 03:29:00 +01: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
Durham Goode
b5e2c4fade bundle2: add op.gettransaction() to handlers that need the lock
A future patch will allow the bundle2 lock be taken lazily. We need to
introduce transaction-gets to each handler that needs the lock.

The tests caught these issues when I added lazy locking.
2015-10-06 14:42:29 -07:00
Pierre-Yves David
84d5d1a440 bundle2: add a way to just forward the bundle2 stream to another user
There is use case for directly forward and bundle2 stream from the peer to a
file (eg: 'hg incoming --bundle'), However ssh peers have no way to know the
'getbundle' is over except for actually interpreting the bundle. So we need to
have the unbundle do the interpreting and forward job.

The function is marked as private to highlight that this is terrible and that we
are sorry.
2015-10-08 01:40:21 -07:00
Pierre-Yves David
9cadff52d0 bundle2: split parameter retrieval and processing
We want to introduce a simple way to forward the content of a bundle2 stream.
For this purpose, we will need to both yield the parameters block and process it
(to apply any behavior change it might indicate).
2015-10-05 01:10:49 -07:00
Pierre-Yves David
c4198a6645 bundle2: allow compressed bundle
This changeset adds support for a 'compression' parameter in bundle2 streams.
When set, it controls the compression algorithm used for the payload part of the
bundle2.

There is currently no usage of this except in tests.
2015-09-23 12:56:12 -07:00
Pierre-Yves David
c6b4571453 bundle20: extract core payload generation in its own function
We are about to allow compressing the core of the bundle2. So we extract the
generation of this bits in its own parts to make this compression phases easier
in a later changesets.
2015-09-23 12:56:05 -07:00
Pierre-Yves David
18caca2d9c unbundle20: allow registering handlers for stream level parameters
As a comment in the code have been asking for, it is now possible to register
piece of code that handle parameters for the stream. I've been wondering is such
function should be class methods or not. I eventually went for externally
decorated methods to stick with the culture of extensibility from an extensions
that apply to bundle2.
2015-09-23 14:00:16 -07:00
Pierre-Yves David
2aa8064fde bundle2: rename error exception class for unsupported feature
The original name explicitly mention "Part", however it is also used outside of
parts related feature. We rename from 'UnsupportedPartError' to
'BundleUnknownFeatureError' to fix this.
2015-09-23 11:44:52 -07:00
Pierre-Yves David
a9d2d02aff bundle: use None when unpacking uncompressed changegroup
Let's be more modern!
2015-09-11 17:05:46 -07:00
Augie Fackler
b9db4815ce bundle2: don't try to recover from a GeneratorExit (issue4785)
GeneratorExit means the other end of the conversation has already
stopped listening, so don't try and yield out error
information. Instead, just let the GeneratorExit propagate normally.

This should resolve esoteric issues observed with servers that have
aggressive timeouts waiting for data to send to clients logging
internal Python errors[0]. This has been observed with both gunicorn's
gevent worker model and with scm-manager's built-in webserver (which
itself is something sitting inside jetty.)


0: Exception RuntimeError: 'generator ignored GeneratorExit' in <generator object getchunks at 0x7fd2f6c586e0> ignored
2015-09-01 15:47:33 -04:00
Gregory Szorc
5f5a2cec0b bundle2: use absolute_import 2015-08-07 19:54:08 -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
Gregory Szorc
0648c6a2bf bundle2: reword debug message for invalid .hgtags data
marmoute requested a follow-up to make the verb the first word.
2015-06-20 18:03:38 -07:00
Pierre-Yves David
0cb42d22dd bundle2.getunbundler: rename "header" to "magicstring"
This is more consistent with the name used in the bundler class. Thanks goes to
Martin von Zweigbergk for pointing this out.
2015-04-07 14:14:27 -07:00
Pierre-Yves David
450e786289 bundle2: provide number of changesets information to 'addchangegroup'
We can now link the two efforts and provided more useful information when
pulling changesets.
2015-06-07 15:57:54 -07:00