Commit Graph

21880 Commits

Author SHA1 Message Date
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
Pierre-Yves David
322ec1b757 push: wrap local 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:15 -07:00
Pierre-Yves David
f2b6946a89 phase: wrap hg phases 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:50:53 -07:00
Pierre-Yves David
7a1c469474 mq: wrap qimport 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:50:07 -07:00
Pierre-Yves David
6f74d76989 mq: wrap qfinish 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:48:51 -07:00
Matt Mackall
241d2dc08e tests: change some #ifs to #requires 2014-08-06 11:53:08 -05:00
Matt Mackall
11be5cc27c tests: replace exit 80 with #require 2014-08-06 11:43:59 -05:00
Matt Mackall
99b86fb9bf run-tests: add #require to abort full test
This allows nuking a bunch of ugly hghave || exit 80 lines.
2014-08-06 10:34:54 -05:00
Augie Fackler
00009ae554 run-tests: add support for xunit test reports
The Jenkins CI system understands xunit reports natively, so this will
be helpful for anyone that wants to use Jenkins for testing hg or
extensions that use run-tests.py for their testing.
2014-08-05 21:17:11 -04:00
Matt Mackall
aeec96d347 contrib: add check-commit hook script to sanity-check commits 2014-08-06 02:45:55 -05:00
Pierre-Yves David
6dbd91e861 shelve: use targetphase while unbundling
This removes the last manual phase movement in shelve.
2014-08-05 13:51:13 -07:00
Pierre-Yves David
8102dcd0f7 changegroup: add a targetphase argument to addchangegroup
This argument controls the phase used for the added changesets. This can be
useful to unbundle in "secret" phase as required by shelve.

This change aims at helping high-level code get rid of manual phase
movement. An important milestone for having phases part of the transaction.
2014-08-05 13:49:38 -07:00
Pierre-Yves David
5f1a5fce7f shelve: do not retract phase boundary by hand
We rely on the internal mechanism to commit the changeset in the right state.
This is similar to what the mq extension is doing.

This is an important change as we plan to move phase movement with the
transaction. Avoiding phase movement from high level code will avoid them the
burden of transaction handling. It is also important to limit the need for
transaction handling as this limits the odds of people messing up. Most common
expected mess-up is to use a different transaction for changesets creation and
phase adjustment.
2014-08-05 14:37:45 -07:00
Pierre-Yves David
7e05742434 commit: update the --secret code to use backupconfig and restoreconfig
Those dedicated methods also preserve all associated data (eg:
sources, lack of value).
2014-08-05 18:53:05 -07:00
Pierre-Yves David
2268a3034c rebase: do not retract phase boundary by hand
We rely on the internal mechanism to commit the changeset in the right phase.
This similar to what the mq extension is doing.

This is an important change as we plan to includes phase movement within the
transaction. Avoiding phase movement from high-level code will avoid the
burden of transaction handling. It is also important to limit the need for
transaction handling as this limits the odds of people messing up. Most common
expected mess-up is code using a different transaction for changeset creation
and phase adjustment.
2014-08-05 13:22:44 -07:00
Pierre-Yves David
c79537766d config: fix restoreconfig of non existing config
When the section, but no value existed, the `del` call raised a key error.
2014-08-05 21:16:24 -07:00
Pierre-Yves David
cc9f66eab2 push: use stepsdone for obsmarkers push
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.
2014-07-31 13:51:17 -07:00
Pierre-Yves David
8ac50232a0 push: introduce a discovery step for obsmarker
The discovery step is still not doing anything smart. But this will allow
extension to wrap it.
2014-07-05 19:32:20 +02:00
Pierre-Yves David
1a0b1222c5 push: move the list of obsmarker to push into the push operation
The list is now carried in the push operation, this will let
extensions override it.
2014-07-05 19:17:09 +02:00
Pierre-Yves David
c3d4f292a8 push: explicitly encode a list of obsmarkers to push
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)
2014-07-04 19:31:49 +02:00
Pierre-Yves David
bbc45b832a merge-tools: add a premerge=keep-merge3 config option
This value leaves premerge markers that includes the merge base too. This is a
the same as what `internal:merge3` would do.
2014-08-04 16:32:41 -07:00
Pierre-Yves David
eab8e275dd merge-tools: make premerge valid values extensible
We want to introduce a version leaving merge3 style markers.
2014-08-04 16:58:39 -07:00
Pierre-Yves David
7680e94cd7 mergetools: add a test for premerge --keep
It works! No surprise.
2014-08-04 16:50:15 -07:00
Pierre-Yves David
c8bde49047 test-merge-tools: introduce a "revision 4" that merges with conflict
We need conflicts to test the premerge=keep configuration.
2014-08-04 16:39:47 -07:00
Pierre-Yves David
16c46d5926 merge: add an internal:merge3 tool
This variant gives access to a feature already present in ``internal:merge``:
displaying merge base content.

In the basic merge (calling ``hg merge``) case, including more context to the
merge markers is an interesting addition.

But this extra information is the only viable option in case conflict from
grafting (, rebase, etc…).

When grafting ``source`` on ``destination``, the parent of ``source`` is
used as the ``base``. When all three changesets add content in the same
location, the marker for ``source`` will contains both ``base`` and ``source``
content. Without the content of base exposed, there is no way for the user
to discriminate content coming from ``base`` and content commit from ``source``.

Practical example (all addition are in the same place):

* ``destination`` adds ``Dest-Content``
* ``base``        adds ``Base-Content``
* ``source``      adds ``Src-Content``

Grafting ``source`` on ``destination`` will produce the following conflict:

  <<<<<<< destination
  Dest-Content
  =======
  Base-Content
  Src-Content
  >>>>>>> source

This that case there is no way to distinct ``base`` from ``source``. As a result
content from ``base`` are likely to slip in the resolution result.

However, adding the base make the situation very clear:

  <<<<<<< destination
  Dest-Content
  ||||||| base
  Base-Content
  ======= base
  Base-Content
  Src-Content
  >>>>>>> source

Once the base is added, the addition from the grafted changeset is made clear.
User can compare the content from ``base`` and ``source`` to make an enlightened
decision during merge resolution.
2014-08-05 14:58:45 -07:00
Pierre-Yves David
0ddace5f8c internal:merge: update documentation
Highlight the fact there are two regions in the markers and what their contents
are. This prepares for the arrival of merge3.
2014-08-05 15:09:54 -07:00
Pierre-Yves David
6120cff637 filemerge: allow the formatting of three labels instead of two
When a third label is provided (to included the base content) it is properly
processed as the two others. Nothing changes if only two labels are provided.
2014-08-05 15:17:38 -07:00
Pierre-Yves David
2fc8f16378 filemerge: drop extra white space
There should be no white space around the brace.
2014-08-05 15:12:22 -07:00
Pierre-Yves David
72d8ebecb8 simplemerge: support three labels when merging
If a third label is provided it will be used for the "base" content:

  <<<<<<< local
  content
  from
  local
  ||||||| base
  former
  common
  =======
  other
  conflicting
  >>>>>>> other
2014-08-05 15:10:50 -07:00
Pierre-Yves David
2017698ec4 simplemerge: burn "minimal" feature to the ground
Matt Mackall said:

  The goal of simplemerge should have always been to be a drop-in
  replacement for RCS merge. Please nuke this minimization thing entirely.

This whole things is now dead.
2014-08-05 14:56:25 -07:00
Pierre-Yves David
0fe23d7392 merge: use no-minimal for premerge too
fade484cb8f6 disabled minimal for `internal:merge` but forgot to also disabled
it for premerge. This is now done.

This gives me an occasion to shamelessly includes my explanation of why this
minimisation feature must disappear:

[this is why it's pointless to reject patches with misspellings in the
description - mpm]

Detailled explanation
=====================


The ``simplemerge`` code use in ``internal:merge`` has a feature called
"minimization". It reprocess conflicting chunks to find common changes
inside them and excludes such common sections from the marker.

This approach seems a significant win at first glance but produces very
confusing results in some other cases.

Simple example
--------------

A simple example is enough to show the benefit of this feature.  In this merge,
both sides change all numbers from letters to digits, but one side is also
changing some values.

  $ cat << EOF > base
  > Small Mathematical Series.
  > One
  > Two
  > Three
  > Four
  > Five
  > Hop we are done.
  > EOF

  $ cat << EOF > local
  > Small Mathematical Series.
  > 1
  > 2
  > 3
  > 4
  > 5
  > Hop we are done.
  > EOF

  $ cat << EOF > other
  > Small Mathematical Series.
  > 1
  > 2
  > 3
  > 6
  > 8
  > Hop we are done.
  > EOF

In the minimalists case, the markers focus on the disagreement between the two
sides.

  $ $TESTDIR/../contrib/simplemerge --print local base other
  Small Mathematical Series.
  1
  2
  3
  <<<<<<< local
  4
  5
  =======
  6
  8
  >>>>>>> other
  Hop we are done.
  warning: conflicts during merge.
  [1]

In the non minimalist case, the whole chunk is included in the conflict marker.
Making it harder spot actual differences.

  $ $TESTDIR/../contrib/simplemerge --print --no-minimal local base other
  Small Mathematical Series.
  <<<<<<< local
  1
  2
  3
  4
  5
  =======
  1
  2
  3
  6
  8
  >>>>>>> other
  Hop we are done.
  warning: conflicts during merge.
  [1]

Practical Advantages of minimalisation: merge of grafted change
---------------------------------------------------------------

This feature can be very useful when a change have been grafted in another
branch and then some change have been made to the grafted code.

  $ cat << EOF > base
  > # empty file
  > EOF

  $ cat << EOF > local
  > def somefunction(one, two):
  >     some = one
  >     stuff = two
  >     are(happening)
  >     here()
  > EOF

  $ cat << EOF > other
  > def somefunction(one, two):
  >     some = one
  >     change = two
  >     are(happening)
  >     here()
  > EOF

The minimalist case recognises the grafted content as similar and highlight the
actual change.


  $ $TESTDIR/../contrib/simplemerge --print local base other
  def somefunction(one, two):
      some = one
  <<<<<<< local
      stuff = two
  =======
      change = two
  >>>>>>> other
      are(happening)
      here()
  warning: conflicts during merge.
  [1]

Again, the non-minimalist case produces a larger conflict. Making it harder to
spot the actual conflict.

  $ $TESTDIR/../contrib/simplemerge --print --no-minimal local base other
  <<<<<<< local
  def somefunction(one, two):
      some = one
      stuff = two
      are(happening)
      here()
  =======
  def somefunction(one, two):
      some = one
      change = two
      are(happening)
      here()
  >>>>>>> other
  warning: conflicts during merge.
  [1]


Practical disadvantage: multiple functions on each side
---------------------------------------------------------------

So, if this "minimalist" help so much, why introduce a setting to disable it?

The issue is that this minimisation will grab any common lines for breaking
chunks. This may result in partial context when solving a merge. The most
simple example is a merge where both side added some (different) functions
separated by blank lines. The "minimalist" approach will recognise the blank
line as "common" and over slice the chunks, turning a simple conflict case into
multiple pairs of conflicting functions.

  $ cat << EOF > base
  > # empty file
  > EOF

  $ cat << EOF > local
  > def function1():
  >     bla()
  >     bla()
  >     bla()
  >
  > def function2():
  >     ble()
  >     ble()
  >     ble()
  > EOF

  $ cat << EOF > other
  > def function3():
  >     bli()
  >     bli()
  >     bli()
  >
  > def function4():
  >     blo()
  >     blo()
  >     blo()
  > EOF

The minimal case presents each function as a separated context.

  $ $TESTDIR/../contrib/simplemerge --print local base other
  <<<<<<< local
  def function1():
      bla()
      bla()
      bla()
  =======
  def function3():
      bli()
      bli()
      bli()
  >>>>>>> other

  <<<<<<< local
  def function2():
      ble()
      ble()
      ble()
  =======
  def function4():
      blo()
      blo()
      blo()
  >>>>>>> other
  warning: conflicts during merge.
  [1]

The non-minimalist approach produces a simpler version with more context in
each block. Solving such conflicts is usually as simple as dropping the 3 lines
dedicated to markers.

  $ $TESTDIR/../contrib/simplemerge --prin --no-minimal local base other
  <<<<<<< local
  def function1():
      bla()
      bla()
      bla()

  def function2():
      ble()
      ble()
      ble()
  =======
  def function3():
      bli()
      bli()
      bli()

  def function4():
      blo()
      blo()
      blo()
  >>>>>>> other
  warning: conflicts during merge.
  [1]

Practical disaster: programing language have a lot of common line
=================================================================

If only blank lines between function where the only frequent content of a code
file. But programming language tend to repeat them self much more often. In that
case, the minimalist approach turns a simple conflict into a massive mess.

Consider this example where two unrelated functions are added on each side.
Those function shares common programming constructs by chance.

  $ cat << EOF > base
  > # empty file
  > EOF

  $ cat << EOF > local
  > def longfunction():
  >     if bla:
  >        foo
  >     else:
  >        bar
  >     try:
  >        ret = some stuff
  >     except Exception:
  >        ret = None
  >     if ret is not None:
  >         return ret
  >     return 0
  >
  > def shortfunction(foo):
  >     goo()
  >     ret = foo + 5
  >     return ret
  > EOF

  $ cat << EOF > other
  > def otherlongfunction():
  >     for x in xxx:
  >        if coin:
  >            break
  >        tutu
  >     else:
  >        bar()
  >     baz()
  >     ret = week()
  >     try:
  >        groumpf = tutu
  >        fool()
  >     except Exception:
  >        zoo()
  >     pool()
  >     if cond:
  >         return ret
  >
  >     # some big block
  >     ret ** 6
  >     koin()
  >     return ret
  > EOF

The minimalist approach will hash the whole conflict into small chunks that
does not match any meaningful semantic and are impossible to solve.

  $ $TESTDIR/../contrib/simplemerge --print local base other
  <<<<<<< local
  def longfunction():
      if bla:
         foo
  =======
  def otherlongfunction():
      for x in xxx:
         if coin:
             break
         tutu
  >>>>>>> other
      else:
  <<<<<<< local
         bar
  =======
         bar()
      baz()
      ret = week()
  >>>>>>> other
      try:
  <<<<<<< local
         ret = some stuff
  =======
         groumpf = tutu
         fool()
  >>>>>>> other
      except Exception:
  <<<<<<< local
         ret = None
      if ret is not None:
  =======
         zoo()
      pool()
      if cond:
  >>>>>>> other
          return ret
  <<<<<<< local
      return 0
  =======
  >>>>>>> other

  <<<<<<< local
  def shortfunction(foo):
      goo()
      ret = foo + 5
  =======
      # some big block
      ret ** 6
      koin()
  >>>>>>> other
      return ret
  warning: conflicts during merge.
  [1]

The non minimalist approach will properly produce a single set of conflict
markers. Highlighting that the two chunk are unrelated. Such conflict from
unrelated content added at the same place is usually solved by dropping the
marker an keeping both content. Something impossible with minimised markers.


  $ $TESTDIR/../contrib/simplemerge --prin --no-minimal local base other
  <<<<<<< local
  def longfunction():
      if bla:
         foo
      else:
         bar
      try:
         ret = some stuff
      except Exception:
         ret = None
      if ret is not None:
          return ret
      return 0

  def shortfunction(foo):
      goo()
      ret = foo + 5
      return ret
  =======
  def otherlongfunction():
      for x in xxx:
         if coin:
             break
         tutu
      else:
         bar()
      baz()
      ret = week()
      try:
         groumpf = tutu
         fool()
      except Exception:
         zoo()
      pool()
      if cond:
          return ret

      # some big block
      ret ** 6
      koin()
      return ret
  >>>>>>> other
  warning: conflicts during merge.
  [1]
2014-07-29 11:55:01 -07:00
Pierre-Yves David
b9d14448be merge: refactor labels selection code
The code is simplified to prepare the future introduction of a third labels for
the merge base.
2014-06-09 23:37:36 -07:00
Pierre-Yves David
4d68940dba push: include phase push in the unified bundle2 push
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".
2014-07-01 23:08:17 +02:00
Pierre-Yves David
bee675a073 push: perform phases discovery before the push
This will allow including phase information in the same bundle2 as the
changesets.
2014-07-30 19:26:47 -07:00
Pierre-Yves David
ce9f85e2a8 push: make discovery extensible
We need to gather all discovery before the unified bundle2 push. We
use the same pattern as bundle2 parts generation.
2014-07-01 17:06:02 +02:00
Pierre-Yves David
421f86b4d6 push: rework the bundle2partsgenerators logic
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!).
2014-07-30 19:04:50 -07:00
Pierre-Yves David
77a2e846ed push: move common heads computation into pushop
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.
2014-07-01 17:27:22 +02:00
Pierre-Yves David
95a8ba3038 push: extract fallback heads computation into pushop
Similar motivation to `futureheads`, we extract the computation into pushop
to make it available early to all possibly interested parties.
2014-07-01 17:20:47 +02:00
Pierre-Yves David
b3209a1336 push: extract future heads computation into 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.
2014-07-01 17:20:31 +02:00
FUJIWARA Katsunori
28e199eab5 cmdutil: use '[committemplate]' section like as map file for style definition
Before this patch, each template definitions for 'changeset*' in
'[committemplate]' section have to be written fully from scratch,
even though many parts of them may be common.

This patch uses '[committemplate]' section like as the map file for
the style definition. All items other than 'changeset' can be referred
from others.

This can reduce total cost of template customization in
 '[committemplate]' section.

When the commit template other than '[committemplate] changeset'
is chosen by 'editform', putting '[committemplate] changeset'
value into the cache of the templater causes unexpected result,
because the templater stores the specified (= chosen) template
definition into own cache as 'changeset' at construction time.

This is the reason why '[committemplate] changeset' can't be referred
from others.
2014-08-02 21:46:27 +09:00
FUJIWARA Katsunori
ec97822d35 cmdutil: look commit template definition up by specified 'editform'
Before this patch, '[committemplate] changeset' definition is shared
between all actions invoking 'commitforceeditor()'.

This prevents template definition from showing action specific
messages: for example, 'hg tag --remove' may need specific
message to call attention, but showing it may be redundant for
other actions.

This patch looks commit template definition up by specified
'editform' introduced by prior patches. 'editform' are
dot-separated list of names, and treated as hierarchical one.
2014-08-02 21:46:27 +09:00
FUJIWARA Katsunori
7b50947677 import: pass 'editform' argument to 'cmdutil.getcommiteditor'
This patch passes 'editform' argument according to the format below:

  COMMAND[.ROUTE]

  - ROUTE: name of route, if there are two or more routes in COMMAND

In this patch, 'normal' and 'bypass' are used as ROUTE.
2014-08-02 21:46:27 +09:00
FUJIWARA Katsunori
4de8382c53 commit: pass 'editform' argument to 'cmdutil.getcommiteditor'
This patch passes 'editform' argument according to the format below:

  COMMAND[.ROUTE]

  - ROUTE: name of route, if there are two or more routes in COMMAND

In this patch, 'normal' and 'amend' are used as ROUTE.
2014-08-02 21:46:27 +09:00
FUJIWARA Katsunori
69635163b7 tag: pass 'editform' argument to 'cmdutil.getcommiteditor'
This patch passes 'editform' argument according to the format below:

  COMMAND[.ROUTE]

  - ROUTE: name of route, if there are two or more routes in COMMAND

In this patch, 'add' and 'remove' are used as ROUTE
2014-08-02 21:46:27 +09:00
FUJIWARA Katsunori
c911495421 graft: pass 'editform' argument to 'cmdutil.getcommiteditor'
This patch passes 'editform' argument according to the format below:

  COMMAND[.ROUTE]

  - ROUTE: name of route, if there are two or more routes in COMMAND

In this patch, ROUTE is omitted.
2014-08-02 21:46:27 +09:00
FUJIWARA Katsunori
70a66564d9 backout: pass 'editform' argument to 'cmdutil.getcommiteditor'
This patch passes 'editform' argument according to the format below:

  COMMAND[.ROUTE]

  - ROUTE: name of route, if there are two or more routes in COMMAND

In this patch, ROUTE is omitted..
2014-08-02 21:46:27 +09:00
FUJIWARA Katsunori
1220ea4bc4 transplant: pass 'editform' argument to 'cmdutil.getcommiteditor'
This patch passes 'editform' argument according to the format below:

  EXTENSION[.COMMAND][.ROUTE]

  - EXTENSION: name of extension
  - COMMAND: name of command, if there are two or more commands in EXTENSION
  - ROUTE: name of route, if there are two or more routes in COMMAND

In this patch, COMMAND and ROUTE are omitted.
2014-08-02 21:46:26 +09:00
FUJIWARA Katsunori
cf19c35fc5 shelve: pass 'editform' argument to 'cmdutil.getcommiteditor'
This patch passes 'editform' argument according to the format below:

  EXTENSION[.COMMAND][.ROUTE]

  - EXTENSION: name of extension
  - COMMAND: name of command, if there are two or more commands in EXTENSION
  - ROUTE: name of route, if there are two or more routes in COMMAND

In this patch:

  - 'shelve' is used as COMMAND
  - ROUTE is omitted
2014-08-02 21:46:26 +09:00
FUJIWARA Katsunori
1829ad7be1 rebase: pass 'editform' argument to 'cmdutil.getcommiteditor'
This patch passes 'editform' argument according to the format below:

  EXTENSION[.COMMAND][.ROUTE]

  - EXTENSION: name of extension
  - COMMAND: name of command, if there are two or more commands in EXTENSION
  - ROUTE: name of route, if there are two or more routes in COMMAND

In this patch:

  - COMMAND is omitted
  - 'normal' and 'collapse' are used as ROUTE
2014-08-02 21:46:26 +09:00
FUJIWARA Katsunori
66fb22c0d4 mq: pass 'editform' argument to 'cmdutil.getcommiteditor'
This patch passes 'editform' argument according to the format below:

  EXTENSION[.COMMAND][.ROUTE]

  - EXTENSION: name of extension
  - COMMAND: name of command, if there are two or more commands in EXTENSION
  - ROUTE: name of route, if there are two or more routes in COMMAND

In this patch:

  - MQ command names (qnew/qrefresh/qfold) are used as COMMAND
  - ROUTE is omitted
2014-08-02 21:46:26 +09:00