We can now directly prevent any evolution-related operation from happening by using
an empty set for outgoing markers. So we detect if no transfers should occur and
use an empty set in this case.
We use the `pushkey` part to exchange bookmark updates within the unified
bundle2 push. Note that this only applies on update (moving a bookmark known on both
sides) since bookmark export (creation of a new bookmark on remote) is apparently
done outside of the _push function.
The discovery of necessary bookmark updates is now done within the "discovery
phase". This opens the door to the inclusion of bookmarks in a unified bundle2
push.
We make a temporary variable for the remote bookmark data and we do not expand
all elements from `bookmark.compare` since we are going to use only one.
Before this patch, there was always an attempt to update bookmark even if prior
steps of the push failed. I cannot see a good semantic reason to do so. We
disable this possibility to simplify the push flow with bundle2. Bookmarks will
be included in the bundle and fail with other steps.
Now that ancestors has the same boolean property as a list, we can stop unrolling
the set of ancestors. This should provide a significant speedup to this step as
ancestor objects are smart and lazy.
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.
We were relying on the phase internals to filter out redundant phase
information from remove. However as we plan to integrate phase
movement inside the transaction, we want to avoid useless transaction
creation on no-op pulls.
Therefore we filter out all the information that already matches the current
repository state. This will let us create a transaction only when there is
actual phase movement needed.
We do not have infrastructure to include obsolescence markers in the bundle2
push from core. But extensions may so we make sure it would not be sent twice.
Sending obsmarkers through pushkey requires extra encoding (since pushkey can't
take binary content) and slicing (since we can hit http header limit). As we
send all obsolescences markers that exists in the repo for each push, we used to
just look at the content of the "obsolete" pushkey namespace (already encoded
and sliced) and send its
content.
However, future changeset will make it possible to push only parts of the
obsmarkers. To prepare this we now explicitly encode a list of markers. The list
of markers is still "all of them" but future changeset will takes care
of that.
The new code uses a "_protected" method but that seems reasonable to keep it
private as this is the is the only external user of it and this whole pushing
obsmarker through pushkey things in fairly hacky already)
Phase push is now included in the same bundle2 push as changesets. We use
multiple pushkey parts to transmit the information. Note that phase moves are
still not part of the repository "transaction".
Instead of a single list of functions, we now have a list of names and
a mapping of names to functions. This simplifies wrapping of steps
from extensions. In the same move, declaration becomes decorator-based
(syntax sugar, nom nom nom!).
Now that both options (push succeed or fall back) live in pushop, we
can move the common heads computation there too. It is a very commonly
accessed attribute so it makes a lot of sense to have it in pushop.
Bundle2 will allow pushing all different parts of the push in a single bundle.
This mean that the discovery for each part needs to be done before trying to
push. Currently we may have different behaviors for phases and obsolescence markers
when the push of changesets fails. For example, information may still be
exchanged for a part of the history where changesets are common but where
phases mismatch. So the preparation of the push need to determine what
information need to be pushed in both situations. And it needs a different set of
heads for this. Therefore we are moving heads computation within pushop for easy
access by all parties. We start with the simplest set of heads.
The ``getbundle`` function was initially design to return a changegroup bundle.
However, bundle2 allows transmitting a wide range of data. Some bundle2
requests may not include a changegroup at all.
Before this changeset, the client would request a changegroup for
``heads=[nullid]`` and receive an empty changegroup.
We introduce an official boolean parameter, ``cg``, that can be set
to false to disable changegroup generation on getbundle. A new bundle2
capability is introduced to let the client know.
When a bundle2 parts generator returns a non callable value, it should not be
used as a reply handler. The changegroup part generator is already having this
case of behavior when there is no changegroup to push. This changeset prevent a
crash for user of the experimentable bundle2 feature.
Instead of explicitly calling a few function to generate part in the bundle, we
now have a list of all part generators. This should make it easier for
extensions to adds new part in the bundle.
This new way to extend the push deprecates the old `_pushbundle2extraparts` way.
When bundle2 push includes more than just changesets, we may have no
changegroup to push yet still have other data to push.
So we now try to performs a bundle2 push in all cases. The check for changegroup
inclusion is moved into the ``_pushb2ctx`` function in charge of creating the
changegroup part.
The bundle2 part is aborted if no actual payload part have been added to the
bundle2.
This attribute will record what steps were performed during the bundle2 push.
This will control whenever the old way push must be performed or skipped. This
will ultimately be used by changegroup, phases, obsmarkers, bookmarks and any
other kind of data ones may want to exchange even when bundle2 support is
missing.
We extract the creation of changegroup related parts into its own function.
This precludes the inclusion of more diverse data during the bundle2 push.
We use a closure to carry the logic that need to be perform when processing the
server reply.
This is the first step of a refactoring that will ease the inclusion of new part
in the bundle2 push and includes more information (like phases) in this push
We need to move the function a bit sooner to be able to group the generation of
`b2x:check:heads` and `b2x:changegroup` part in an external function. We move it
sooner to preserve parts creation order bundle2 tests rely on. At the ends of this
refactoring the `_pushbundle2extraparts` will be replaced by another mechanism
anyway.
When bundle2 was enabled, if hg pull had no commits to pull, it would print
'no changes found' and then download the entire repository from the server. This
was caused by heads and common being set to None, which gets treated as
heads=cl.heads() and common=[nullid], which means download the entire repo.
Pulling bundles without a changegroup is a valid use case (like if we're just
updating bookmarks), so this modifes the bundle code to allow not adding
changegroups.
This is backport of 26ad3517a3a2.
During pulls bundle2 was checking server.bundle2, but during pushes it was
checking experimental.bundle2. This makes them both experimental.bundle2.
This is a backport of a9334b37b19a
We make sure any exceptions raised during the whole span of handling bundle2
processing are decorated. This let us catch exceptions raised by hooks prior to
transaction commit.
If the heads on the server differ from the ones reported seen by the client at
bundle time, we raise a PushRaced exception. However, the part raising the
exception was broken.
To fix it, we move the PushRaced class in the error module so it can be
accessible everywhere without an import cycle.
A test is also added to prevent regression.