Commit Graph

127 Commits

Author SHA1 Message Date
Pierre-Yves David
2f46ffacac checkheads: use a "lazyancestors" object for allfuturecommon
Instead of walking all ancestors to compute the full set we now check membership
lazily. This massively speed.

On a million-ish revision repository, this remove 14 seconds from the push logic,
making the checkheads function disappear from profile.
2017-06-05 13:44:15 +01:00
Pierre-Yves David
8eeebc599c checkheads: use "revnum" in the "allfuturecommon" set
The obsolete post-processing needs to know the extend of the pushed set. The
way it is implemented is... suboptimal. It build a full set of all nodes in the
pushset and it does so using changectx. We have much better API for this now.
The simplest is to use the existing lazy ancestors computation. That logic uses
revnum and not node (for good reason) so we start with updating the
post-processing code to handle a "allfuturecommon" set containing revision
numbers.
2017-06-05 13:37:04 +01:00
Pierre-Yves David
12f527e6f1 checkheads: use 'nodemap.get' to convert nodes to revs
We are about to call 'torev' on node that might be locally missing. In this
case, 'nodemap.revs' will return None (something valid in our usecase) while
'changelog.rev' would raise an exception.

We make this change in a distinct changeset to show it does not impact the
tests.
2017-06-05 15:20:20 +01:00
Pierre-Yves David
a0b8c4a72d checkheads: pass "ispushed" function to the obsmarkers logic
We are about to make "allfuturecommon" a set of revs instead of a set of nodes.
The function updated in this patch do not needs to know about these details so
we just pass it a 'ispushed(node)' function. This will simplify the next
changeset.
2017-06-05 15:17:47 +01:00
Pierre-Yves David
a74c131fb4 push: add a way to allow concurrent pushes on unrelated heads
Client has a mechanism for the server to check that nothing changed server side
since the client prepared a push. That check is wide and any head changed on
the server will lead to an aborted push. We introduce a way for the client to
send a less strict checking. That logic will check that no heads impacted by
the push have been affected. If other unrelated heads (including named branches
heads) have been affected, the push will proceed.

This is very helpful for repositories with high developers traffic on different
heads, a common setup.

That behavior is currently controlled by an experimental option. The config
should live in the "server" section but bike-shedding of the name will happen
in the next changesets. Servers advertise this capability through a new bundle2
capability 'checkeads', using the value 'related'.

The 'test-push-race.t' is updated to check that new capabilities on the
documented cases.
2017-05-29 05:53:58 +02:00
Pierre-Yves David
995a8250c6 headsummary: expose the 'discardedheads' set in the headssummary
That information will be useful to detect push race on related part of the
history.

See next changeset for details.
2017-05-29 05:52:13 +02:00
Pierre-Yves David
03a21b39f6 checkheads: perform obsolescence post processing directly in _headssummary
The goal is to have the function directly return something meaningful and
useful for the whole pull.

Note: we skip adding post-processing in '_oldheadssummary' because if a client
is too old for branchmap it will be too old for obsolescence too.
2017-05-29 05:47:27 +02:00
Pierre-Yves David
d0a234e185 headssummary: directly feed the function with the 'pushop' object
Our goal is to be able to perform the post processing directly into the
'_headssummary' function. However before this patch the '_headsummary' function
only had access to repo, remote, outgoing while the '_postprocessobsolete'
function takes a 'pushop' object.  Experience shows that having the 'pushop'
object helps extensions so we update '_headssummary' to take a pushop
object as argument.
2017-05-29 10:56:00 +02:00
Pierre-Yves David
7d1cdfda7e checkheads: gather the postprocessing with other obsolescence specific code
We extract this function from the loop and gather it with the rest of the
obsolescence specific code. That will help to clarify the move of the whole logic
inside the "heads summary" computation.
2017-05-29 05:45:59 +02:00
Pierre-Yves David
92378aada1 checkheads: simplify the code around obsolescence post-processing
The 'discardedheads' return become unused and the relationship between newheads
and newhs can be clarified. Our next goal here is to be able to extract the
_postprocessobsolete call outside of the loop.

We keep returning the 'discardedheads' because we'll start using it again soon
in this series.
2017-05-29 05:23:30 +02:00
Pierre-Yves David
8ab44eb083 checkheads: drop now unused filtering of 'unsyncedheads'
Now that unsynced heads are no longer in the function inputs or returns, we can
simplify the code a bit.
2017-05-29 05:21:38 +02:00
Pierre-Yves David
12e4c6dacb checkheads: clarify that we no longer touch the head unknown locally
Since b5554fb97d46, heads unknown locally no longer get any post processing
from obsolescence markers. We clarify this fact by only feeding the list of
locally known new heads to the function. This simplification of the input will
help moving that post-processing earlier in the function.
2017-05-29 05:20:09 +02:00
Pierre-Yves David
25c3e1db72 headssummary: ensure all returned lists are sorted
This is a simple step that will help to keep a stable output in coming
refactoring.
2017-05-29 05:33:59 +02:00
Pierre-Yves David
20859d5371 discovery: also use lists for the returns of '_oldheadssummary'
The '_headssummary' function is documenting and using list objects in its
return.  We now use them in _oldheadssummary too for consistency. This does not
affect any usages of these values.
2017-05-29 05:37:19 +02:00
Pierre-Yves David
60bb5d96f7 obscheckhead: skip context creation to test phase
On repository with many many heads, this is called often enough to show an
overhead to appears in some profile. So we skip the 'changectx' creation to test
the node phases.
2017-05-19 12:35:14 +02:00
Martin von Zweigbergk
c3406ac3db cleanup: use set literals
We no longer support Python 2.6, so we can now use set literals.
2017-02-10 16:56:29 -08:00
Yuya Nishihara
532f16e237 discovery: prevent crash caused by prune marker having no parent data
If a marker has no parent information, parents field is set to None, which
caused TypeError. I think this shouldn't normally happen, but somehow
I have such marker in my repo.
2017-04-19 23:10:05 +09:00
Pierre-Yves David
551d0f8ee6 checkheads: upgrade the obsolescence postprocessing logic (issue4354)
The previous logic had many shortcoming (eg: looking at the head only, not
handling prune, etc...), the new logic use a more robust approach:

For each head, we check if after the push all changesets exclusive to this heads
will be obsolete. If they are, the branch considered be "replaced".

To check if a changeset will be obsolete, we simply checks:

* the changeset phase

* the existence of a marker relevant to the "pushed set" that affects the
  changesets..

This fixes two major issues of the previous algorithm:

* branch partially rewritten (eg: head but not root) are no longer detected as
  replaced,

* Prune are now properly handled.

(This implementation was introduction in the evolve extension, version 6.0.0.)

This new algorithm has an extended number of tests, a basic one is provided
in this patch. The others will be introduced in their own changeset for clarity.

In addition, we stop trying to process heads unknown locally, we do not have
enough data to take an informed decision so we should stop pretending we do.
This reflect a test that is now update.
2017-04-15 02:55:18 +02:00
Pierre-Yves David
3e8a941a87 checkheads: extract obsolete post processing in its own function
The checkheads function is long and complex, extract that logic in a subfunction
is win in itself. As the comment in the code says, this postprocessing is
currently very basic and either misbehave or fails to detect valid push in many
cases. My deeper motive for this extraction is to be make it easier to provide
extensive testing of this case and strategy to cover them. Final test and logic
will makes it to core once done.
2017-03-21 23:30:13 +01:00
timeless
a57e86590a discovery: use single quotes in use warning 2016-09-20 23:47:30 +00:00
Ryan McElroy
78bbaf76bd discovery: explicitly check for None in outgoing init
c8fefe878a71 introduced default params for discovery.outgoing(), but it used a
falsy check instead of an explicit check for None. The result is that callers
that passed in an empty list would have that list overridden by the defaults,
which is not the expected behavior.

This was discovered by changes to the test-pushrebase.t test in Facebook's
repository of mercurial extensions.
2016-09-06 09:43:25 -07:00
Pierre-Yves David
cca37f1814 outgoing: add a 'missingroots' argument
This argument can be used instead of 'commonheads' to determine the 'outgoing'
set. We remove the outgoingbetween function as its role can now be handled by
'outgoing' itself.

I've thought of using an external function instead of making the constructor
more complicated. However, there is low hanging fruit to improve the current
code flow by storing some side products of the processing of 'missingroots'. So
in my opinion it make senses to add all this to the class.
2016-08-09 22:31:38 +02:00
Pierre-Yves David
a9e69178e3 outgoing: adds some default value for argument
We are about to introduce a third option to create an outgoing object:
'missingroots'. This argument will be mutually exclusive with 'commonheads' so
we implement some default value handling in preparation.

This will also help use to make more use of outgoing creation around the code
base.
2016-08-09 15:55:44 +02:00
Pierre-Yves David
f460bb8823 outgoing: pass a repo object to the constructor
We are to introduce more code constructing such object in the code base. It will
be more convenient to pass a repository object, all current users already
operate at the repository level anyway. More changes to the contructor argument
are coming in later changeset.
2016-08-09 15:26:53 +02:00
Gregory Szorc
9f5f743c8a discovery: move code to create outgoing from roots and heads
changegroup.changegroupsubset() contained somewhat low-level code for
constructing an "outgoing" instance from a list of roots and heads
nodes. It feels like discovery.py is a more appropriate location for
this code.

This code can definitely be optimized, as outgoing.missing will
recompute the set of changesets we've already discovered from
cl.between(). But code shouldn't be refactored during a move, so
I've simply inserted a TODO calling attention to that.
2016-08-03 22:07:52 -07:00
liscju
6d9c9237d1 bookmarks: allow pushing active bookmark on new remote head (issue5236)
Before 'hg push -B .' on new remote head complained with:
abort: push creates new remote head ...

It was because _nowarnheads was not expanding active bookmark
name, so it didn't add active bookmark "proper" name to no
warn heads list.
2016-05-24 23:36:27 +02:00
Ryan McElroy
3f80624a78 discovery: pass pushop to _nowarnheads
Previously, we passed only enough information to _nowarnheads to perform the old
calculation. However, extensions may want to use more information in this
calculation. Now that pushop is extensible, extensions will often want access
to the additional fields they have added to the pushop, so pass that through.

Specifically, the remotenames extension will use this information to allow
pushing new heads that are bookmarked without requiring --force.
2015-11-10 11:16:25 -08:00
Ryan McElroy
f7b3bc72e8 exchange: pass pushop to discovery.checkheads
Previously, we passed a bunch of parameters to discovery.checkheads, but all
of the arguments can be fetched out of pushop, which may contain a lot more
useful information for extensions now that pushop is extensible.
2015-11-10 11:13:21 -08:00
Ryan McElroy
4e01fb3c0d discovery: factor out calculation of heads to not warn about
In addition to taking a step towards getting an unreasonably large function
factored into smaller, more manageable functions, this will allow extensions
such as remotenames have more control over what pushes are allowed or not.
2015-11-06 09:48:24 -08:00
Matt Mackall
afeb6dfab1 bookmarks: don't allow pushing new head for existing mark with -B (issue4400) 2015-10-21 16:21:27 -05:00
Pierre-Yves David
fb6955396c discovery: put trivial branch first
Having the simple and tiny branch of the conditional first help readability. The
"else" that appears after a screen of code is harder to relate to a conditional.
2015-10-12 00:45:24 -07:00
Pierre-Yves David
501c6cbdbc discovery: reference relevant bug in the faulty code
We extend the comment about this code flaw with more code flaw.
2015-10-09 15:44:00 -07:00
Pierre-Yves David
38aa2ec3c6 discovery: fix a typo in a comment
The idea here is that the code is imperfect, not that it is impossible to get
something behaving properly.
2015-10-09 15:37:05 -07: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
Pierre-Yves David
3f7eb46ea2 discovery: rename 'error' to 'errormsg'
The variable 'error' conflict with the module name that we would like to import
and use in a coming changeset.
2015-10-05 22:29:57 -07:00
Gregory Szorc
3ff440a6fc discovery: use absolute_import 2015-08-08 19:07:11 -07:00
Michael O'Connor
824e19a989 discovery: don't compute allfuturecommon when it won't be used
In repos with many changesets, the computation of allfuturecommon
can take a significant amount of time.  Since it's only used if
there's an obsstore, don't compute it otherwise.
2015-04-13 09:54:36 -04:00
Jordi Gutiérrez Hermoso
8eb132f5ea style: kill ersatz if-else ternary operators
Although Python supports `X = Y if COND else Z`, this was only
introduced in Python 2.5. Since we have to support Python 2.4, it was
a very common thing to write instead `X = COND and Y or Z`, which is a
bit obscure at a glance. It requires some intricate knowledge of
Python to understand how to parse these one-liners.

We change instead all of these one-liners to 4-liners. This was
executed with the following perlism:

    find -name "*.py" -exec perl -pi -e 's,(\s*)([\.\w]+) = \(?(\S+)\s+and\s+(\S*)\)?\s+or\s+(\S*)$,$1if $3:\n$1    $2 = $4\n$1else:\n$1    $2 = $5,' {} \;

I tweaked the following cases from the automatic Perl output:

    prev = (parents and parents[0]) or nullid
    port = (use_ssl and 443 or 80)
    cwd = (pats and repo.getcwd()) or ''
    rename = fctx and webutil.renamelink(fctx) or []
    ctx = fctx and fctx or ctx
    self.base = (mapfile and os.path.dirname(mapfile)) or ''

I also added some newlines wherever they seemd appropriate for readability

There are probably a few ersatz ternary operators still in the code
somewhere, lurking away from the power of a simple regex.
2015-03-13 17:00:06 -04:00
Pierre-Yves David
78f473bc9b discovery: prevent crash on unknown remote heads with old repo (issue4337)
When a remote is not capable of the `branchmap` wireproto command, we denote
incoming heads with None. This leads to a crash in the code in charge of
displaying the list of unknown remote heads.

We now properly detect this case and display a shorter message in this case.

The reason for this  `set([None])` value is now documented.
2014-08-14 16:26:41 -07:00
Stephen Lee
05934f0bb8 discovery: if a push would create a new head, mention the bookmark name if any 2014-03-08 19:02:39 +11:00
Mads Kiilerich
bdb0a37b31 discovery: don't report all "unsynced" remote heads (issue4230)
49e52fbb2acd made discovery more helpful - too helpful for some extreme use
cases.

Instead, we arbitrarily limit the list it at 4 and add 'or more'.
2014-04-24 16:47:22 +02:00
Mads Kiilerich
8c0ff878d1 discovery: make "note: unsynced remote changes!" less serious than a warning
This situation is not necessarily a problem and do not deserve a warning. It is
just some information that can guide the user in understanding what is going
on.

Making it 'debug' would usually not give the hint when it is relevant so we
make it a 'status' message.
2014-02-07 17:24:12 +01:00
Mads Kiilerich
303021da0b discovery: improve "note: unsynced remote changes!" warning
This message frequently caused confusion. "unsynced" is not a well established
user-facing concept in Mercurial and the message was not very specific or
helpful.

Instead, show a message like:
  remote has heads on branch 'default' that are not known locally: 6c0482d977a3

This message will also (when relevant) be shown before aborting on "push
creates new remote head".

A similar (but actually very different) message was addressed in cbd5a12a601a.
2014-02-06 02:19:38 +01:00
Matt Mackall
5a04f42dce push: backout b359130ef1bc due to test failures 2014-02-09 17:31:26 -06:00
Mads Kiilerich
fee088299f discovery: improve "note: unsynced remote changes!" warning
This note (which actually is a warning) frequently caused confusion.
"unsynced" is not a well established user-facing concept in Mercurial and the
message was not very specific or helpful.

Instead, show a messages like:
  remote has heads on branch 'default' that are not known locally: 6c0482d977a3
and show it before aborting on "push creates new remote head". This will also
give more of a hint in the case where the branch has been closed remotely and
'hg heads' thus not would show any new heads after pulling.

A similar (but actually very different) message was addressed in cbd5a12a601a.
2014-02-06 02:19:38 +01:00
Mads Kiilerich
a2af430785 discovery: cleanup of variable names and comments 2014-02-06 02:17:48 +01:00
Pierre-Yves David
df72d3d98f discovery: stop using nodemap for membership testing
Nodemap is not aware of filtering so we need to ask the changelog itself if a
node is known. This is probably a bit slower but such check does not dominated
discovery time. This is necessary if we want to run discovery on filtered repo.
2013-11-15 23:28:43 -05:00
Stephen Lee
7b97b6250a bookmarks: allow push -B to create a new remote head (issue2372)
Push is currently allowed to create a new head if there is a remote
bookmark that will be updated to point to the new head. If the
bookmark is not known remotely then push aborts, even if a -B argument
is about to push the bookmark. This change allows push to continue in
this case. This does not require a wireproto force.
2013-11-11 21:16:54 +11:00
Mads Kiilerich
a4925d4784 discovery: make note messages for new heads more readable 2013-11-16 15:46:29 -05:00
Mads Kiilerich
d93d477327 discovery: tweak error message for multiple branch heads 2013-11-16 15:46:29 -05:00