Commit Graph

586 Commits

Author SHA1 Message Date
Siddharth Agarwal
54dd91b4db _checkunknownfiles: turn 'conflicts' into a set
We'll check for membership in this set in an upcoming patch.
2016-01-02 03:02:57 -08:00
Siddharth Agarwal
3e662143bb checkunknownfiles: make control flow clearer
In particular, make it clear that we only check for and abort on conflicts if
force is not true.
2016-01-02 03:02:57 -08:00
Siddharth Agarwal
6ff835640d _checkunknownfiles: rename 'aborts' to 'conflicts'
In upcoming patches we'll be able to do more useful things than aborting.
2016-01-02 03:02:57 -08:00
Matt Mackall
d7ec07e23e merge with stable 2016-01-02 02:13:56 +01:00
Siddharth Agarwal
a6934b01c3 merge: while checking for unknown files don't follow symlinks (issue5027)
Previously, we were using Python's native 'os.path.isfile' method which follows
symlinks. In this case, since we're operating on repo contents, we don't want
to follow symlinks.

There's a behaviour change here, as shown by the second part of the added test.
Consider a symlink 'f' pointing to a file containing 'abc'. If we try and
replace it with a file with contents 'abc', previously we would have let it
though. Now we don't. Although this breaks naive inspection with tools like
'cat' and 'diff', on balance I believe this is the right change.
2015-12-28 22:51:37 -08:00
Augie Fackler
1b827711c9 manifestmerge: have manifest do matching before diffing
This means that the diff code does less work, potentially
significantly less in the case of treemanifests. It also should ease
implementation with narrowed clone cases (such as narrowhg) when we
don't always have the entire set of treemanifest revlogs locally.

As far as I can tell, this codepath is currently only used by record,
so it'll probably die in the near future, and then narrowhg won't have
to worry about composing with some unknown matching system.
2015-12-14 20:57:21 -05:00
Augie Fackler
86f88ad861 merge: improve clarity of table in update docstring 2015-10-23 06:06:22 -04:00
Siddharth Agarwal
307771ef0d merge.applyupdates: call driverconclude after performing merge actions
This will be a chance for the merge driver to finish resolving or generating
any driver-resolved files.

As before, having a separate error state from 'unresolved' is too big a
refactoring for now, so we hack around it by setting unresolved to a positive
value when necessary.
2015-10-15 01:22:01 -07:00
Siddharth Agarwal
671581b397 merge.applyupdates: call driverpreprocess before starting merge actions
We also need to update our internal state to whatever state driverpreprocess
leaves it in.

Adding an error state separate from the unresolved count is too big a
refactoring for now, so we hack around it by setting it to a positive value to
indicate an error state.
2015-10-15 01:19:10 -07:00
Siddharth Agarwal
93aaae5f6a merge: add stubs for preprocess and conclude steps of merge driver
The exact semantics for what should happen (particularly with respect to error
handling) are still a bit hard to pin down, so I think it's better to
experiment with it as an extension for now. For now this stub will act as a
convenient point for extensions to hook on.
2015-10-15 01:17:29 -07:00
Siddharth Agarwal
fe759d6960 merge.mergestate: set merge driver state to 's' if there's none present
This allows mergestate.mdstate() to return 's' if there's nothing to be done on
the merge driver end.
2015-10-15 01:06:29 -07:00
Siddharth Agarwal
793db02056 merge.mergestate: only check for merge driver when property is accessed
Otherwise 'hg update --clean', 'hg rebase --abort' etc wouldn't work.
2015-10-15 01:04:46 -07:00
Siddharth Agarwal
f4dc777bce merge.mergestate: add a way to get the merge driver state
This will be useful to check what the status of the merge driver is.
2015-10-15 00:57:56 -07:00
Siddharth Agarwal
0eb994cb79 merge.mergestate: add a way to get the other side of the merge
It's surprising there was no API at all for this until now. In any case this
will be needed from custom merge drivers.
2015-10-15 00:49:07 -07:00
FUJIWARA Katsunori
75f4bab4a5 merge: make in-memory changes visible to external update hooks
c67339617276 (while 3.4 code-freeze) made all 'update' hooks run after
releasing wlock for visibility of in-memory dirstate changes. But this
breaks paired invocation of 'preupdate' and 'update' hooks.

For example, 'hg backout --merge' for TARGET revision, which isn't
parent of CURRENT, consists of steps below:

  1. update from CURRENT to TARGET
  2. commit BACKOUT revision, which backs TARGET out
  3. update from BACKOUT to CURRENT
  4. merge TARGET into CURRENT

Then, we expects hooks to run in the order below:

  - 'preupdate' on CURRENT for (1)
  - 'update'    on TARGET  for (1)
  - 'preupdate' on BACKOUT for (3)
  - 'update'    on CURRENT for (3)
  - 'preupdate' on TARGET  for (4)
  - 'update'    on CURRENT/TARGET for (4)

But hooks actually run in the order below:

  - 'preupdate' on CURRENT for (1)
  - 'preupdate' on BACKOUT for (3)
  - 'preupdate' on TARGET  for (4)
  - 'update'    on TARGET  for (1), but actually on CURRENT/TARGET
  - 'update'    on CURRENT for (3), but actually on CURRENT/TARGET
  - 'update'    on CURRENT for (4), but actually on CURRENT/TARGET

Root cause of the issue focused by c67339617276 is that external
'update' hook process can't view in-memory changes (especially, of
dirstate), because they aren't written out until the end of
transaction (or wlock).

Now, hooks can be invoked just after updating, because previous
patches made in-memory changes visible to external process.

This patch may break backward compatibility from the point of view of
"scheduling hook execution", but should be reasonable because 'update'
hooks had been executed in this order before 3.4.

This patch tests "hg backout" and "hg unshelve", because the former
activates the transaction before 'update' hook invocation, but the
former doesn't.
2015-10-17 01:15:34 +09:00
FUJIWARA Katsunori
106983607a dirstate: make dirstate.write() callers pass transaction object to it
Now, 'dirstate.write(tr)' delays writing in-memory changes out, if a
transaction is running.

This may cause treating this revision as "the first bad one" at
bisecting in some cases using external hook process inside transaction
scope, because some external hooks and editor process are still
invoked without HG_PENDING and pending changes aren't visible to them.

'dirstate.write()' callers below in localrepo.py explicitly use 'None'
as 'tr', because they can assume that no transaction is running:

  - just before starting transaction
  - at closing transaction, or
  - at unlocking wlock
2015-10-17 01:15:34 +09:00
Siddharth Agarwal
e65ca7df8c merge.mergestate: add a generator for driver-resolved files
Just like for unresolved files above, we need to be able to tell what files are
driver-resolved.
2015-10-14 15:01:07 -07:00
Augie Fackler
b184da51f2 merge: rework manifestmerge to use a matcher
This opens the door to working slightly more closely with the manifest
type and letting it optimize out some of the diff comparisons for us,
and also makes life significantly easier for narrowhg.
2015-12-14 20:47:22 -05:00
Augie Fackler
a84cc516e7 merge: restate calculateupdates in terms of a matcher
Once we get a matcher down into manifestmerge, we can make narrowhg
work more easily and potentially let manifest.match().diff() do less
work in manifestmerge.
2015-12-14 20:37:41 -05:00
Augie Fackler
0a19647501 merge: have merge.update use a matcher instead of partial fn
This is relatively rarely used functionality, but migrating this to a
matcher will make future work on narrow clones more feasible.
2015-12-14 18:54:03 -05:00
Martin von Zweigbergk
8e7f0fdda8 merge: refuse update/merge if there are unresolved conflicts (BC)
We currently allow updating and merging (with --force) when there are
unresolved merge conflicts, as long as there is only one parent of the
working copy. Even worse, when updating to another revision
(linearly), if one of the unresolved files (including any conflict
markers in the working copy) can now be merged cleanly with the target
revision, the file becomes marked as resolved.

While we could potentially allow updates that affect only files that
are not in the set of unresolved files, that's considerably more work,
and we don't have a use case for it anyway. Instead, let's keep it
simple and refuse any merge or update (without -C) when there are
unresolved conflicts.

Note that test-merge-local.t explicitly checks for conflict markers
that get carried over on update. It's unclear if that was intentional
or not, but it seems bad enough that we should forbid it. The simplest
way of fixing the test case is to leave the conflict markers in place
and just mark the files resolved, so let's just do that for now.
2015-12-07 20:43:24 -08:00
Andrew Halberstadt
f18899ffa6 merge.graft: add option to keep second parent
Currently merge.graft re-writes the dirstate so only a single
parent is kept. For some cases, like evolving a merge commit,
this behaviour is not desired. More specifically, this is
needed to fix issue4389.
2015-12-03 23:01:59 -05:00
Siddharth Agarwal
106338a190 merge: move almost all change/delete conflicts to resolve phase (BC) (API)
We have finally laid all the groundwork to make this happen.

The only change/delete conflicts that haven't been moved are .hgsubstate
conflicts. Those are trickier to deal with and well outside the scope of this
series.

We add comprehensive testing not just for the initial selections but also for
re-resolves and all possible dirstate transitions caused by merge tools. That
testing managed to shake out several bugs in the way we were handling dirstate
transitions.

The other test changes are because we now treat change/delete conflicts as
proper merges, and increment the 'merged' counter rather than the 'updated'
counter. I believe this is the right approach here.

For third-party extensions, if they're interacting with filemerge code they
might have to deal with an absentfilectx rather than a regular filectx.

Still to come:
- add a 'leave unresolved' option to merges
- change the default for non-interactive change/delete conflicts to be 'leave
  unresolved'
- add debug output to go alongside debug outputs for binary and symlink file
  merges
2015-11-25 14:25:33 -08:00
Siddharth Agarwal
ed64d46a37 merge.recordupdates: mark 'a' files as added unconditionally
See the previous patch for why we do this.
2015-11-24 15:26:51 -08:00
Siddharth Agarwal
3a27c524dc merge: add a new action type representing files to add/mark as modified
This is somewhat different from the currently existing 'a' action, for the
following case:

- dirty working copy, with file 'fa' added and 'fm' modified
- hg merge --force with a rev that neither has 'fa' nor 'fm'
- for the change/delete conflicts we pick 'changed' for both 'fa' and 'fm'.

In this case 'branchmerge' is true, but we need to distinguish between 'fa',
which should ultimately be marked added, and 'fm', which should be marked
modified.

Our current strategy is to just not touch the dirstate at all. That works for
now, but won't work once we move change/delete conflicts to the resolve phase.
In that case we may perform repeated re-resolves, some of which might mark the
file removed or remove the file from the dirstate. We'll need to re-add the
file to the dirstate, and we need to be able to figure out whether we mark the
file added or modified. That is what the new 'am' action lets us do.
2015-11-30 10:19:39 -08:00
Siddharth Agarwal
ae700a3344 mergestate: add a cached property accessor for the local context
This is going to be useful in an upcoming patch. We make this a public accessor
because this is also going to be useful for custom merge drivers.
2015-11-30 10:03:21 -08:00
Siddharth Agarwal
71a05a4daf mergestate: raise exception if otherctx is accessed but _other isn't set
We don't want to inadvertently return the workingctx (self._repo[None]).
2015-11-30 10:05:09 -08:00
Siddharth Agarwal
c40efd7aa0 mergestate: explicitly forget 'dc' conflicts where the deleted side is picked
Once we move change/delete conflicts into the resolve phase, a 'dc' file might
first be resolved by picking the other side, then later be resolved by picking
the local side. For this transition we want to make sure that the file goes
back to not being in the dirstate.

This has no impact on conflicts during the initial merge.
2015-11-23 18:03:25 -08:00
Siddharth Agarwal
c655a316e8 merge.applyupdates: add all actions returned from merge state
At the moment this is a no-op (the only actions defined are 'r', 'a' and 'g'),
but soon we're going to add other sorts of actions to the dictionary returned
from mergestate.actions().
2015-11-23 19:06:15 -08:00
Siddharth Agarwal
06ed2cbe50 merge.applyupdates: create absentfilectxes for change/delete conflicts
At the moment no change/delete conflicts get to this point -- we're going to
make that happen in an upcoming patch.
2015-11-22 21:58:28 -08:00
Siddharth Agarwal
5b40330cf9 mergestate: add methods to queue files to remove, add or get
These are meant for use by custom merge drivers that might want to modify the
dirstate. Dirstate internal consistency rules require that all removes happen
before any adds -- this means that custom merge drivers shouldn't be modifying
the dirstate directly.
2015-11-22 21:59:52 -08:00
Siddharth Agarwal
be9444426c mergestate: add a way to record pending dirstate actions
We're going to use this in resolve in the next patch.
2015-11-20 16:55:01 -08:00
Siddharth Agarwal
76ecd9e872 merge.recordupdates: don't require action keys to be present in dict
We're going to use this function for a much smaller set of actions in the next
patch. It's easier to do this than to backfill the dict we pass in.
2015-11-15 21:55:46 -08:00
Siddharth Agarwal
d2620ef53f merge.applyupdates: extend action queues with ones returned from mergestate
These queues will always be empty at the moment -- we're going to fill them up
in upcoming patches.
2015-11-20 11:26:31 -08:00
Siddharth Agarwal
1e4024e0f1 mergestate: add a method to compute actions to perform on dirstate
We're going to use this to extend the action lists in merge.applyupdates.

The somewhat funky return value is to make passing this dict directly into
recordactions easier. We're going to exploit that in an upcoming patch.
2015-11-20 16:43:25 -08:00
Siddharth Agarwal
b86e19fd45 merge.applyupdates: use counters from mergestate
This eliminates a whole bunch of duplicate code and allows us to update the
removed count for change/delete conflicts where the delete action was chosen.
2015-11-20 16:37:39 -08:00
Siddharth Agarwal
f919bd4f7b mergestate: add a function to return the number of unresolved files
Note that unlike the other functions, this is based on the persistent
mergestate.
2015-11-20 16:18:51 -08:00
Siddharth Agarwal
8dd9d0304c mergestate: add a method to return updated/merged/removed counts
This will not only allow us to remove a bunch of duplicate code in applyupdates
in an upcoming patch, it will also allow the resolve interface to be a lot
simpler: it doesn't need to return the dirstate action to applyupdates.
2015-11-20 16:17:54 -08:00
Siddharth Agarwal
dd58f25087 mergestate._resolve: don't return the action any more
This is a partial backout of an earlier diff -- now that we're storing the
results in a dict, we don't actually need this any more.
2015-11-20 16:32:47 -08:00
Siddharth Agarwal
aaac3ed514 mergestate._resolve: store return code and action for each file
We're going to need this to compute (a) updated/merged/unresolved counts, and
(b) actions to perform on the dirstate.
2015-11-20 16:08:22 -08:00
Siddharth Agarwal
5d6cb7e78f mergestate.add: store absentfilectxes as nullhex
This is the most natural way to represent these files. We also need to make
sure we don't try to store these files in the merge store.
2015-11-14 00:07:11 -08:00
Siddharth Agarwal
328287680c mergestate._resolve: handle change/delete conflicts
We will represent a deleted file as 'nullhex' in the in-memory and on-disk
merge states. We need to be able to create absentfilectxes in that case, and
delete the file from disk rather than try to write it out.
2015-11-20 01:14:15 -08:00
Siddharth Agarwal
f5fc173bec merge.mergestate: compute dirstate action
In upcoming patches we're going to queue these actions up to be applied to the
dirstate at the end.
2015-11-19 10:50:02 -08:00
Siddharth Agarwal
4904ded295 filemerge: return whether the file was deleted
This is required for change/delete conflict resolution -- see previous patches
for more details.
2015-11-18 14:22:52 -08:00
Siddharth Agarwal
c5b488f2d2 mergestate: allow storing and retrieving change/delete conflicts
We introduce a new record type, 'C', to indicate change/delete conflicts. This
is a separate record type because older versions of Mercurial will not be able
to handle these conflicts.

We aren't actually storing any change/delete conflicts yet -- that will come in
future patches.
2015-11-18 15:46:45 -08:00
Siddharth Agarwal
4a78a436f9 mergestate: handle additional record types specially
This works around a bug in older Mercurial versions' handling of the v2 merge
state.

We also add a bunch of tests that make sure that
(1) we correctly abort when the merge state has an unsupported record type
(2) aborting the merge, rebase or histedit continues to work and clears out the
    merge state.
2015-11-18 15:46:45 -08:00
Siddharth Agarwal
a19a04c7f9 mergestate: move binary format documentation into _readrecordsv2
This is too low-level to be the top-level documentation for mergestate. We're
restricting the top-level documentation to only be about what consumers of the
mergestate and anyone extending it need to care about.
2015-11-18 16:39:30 -08:00
Siddharth Agarwal
0d7932e904 mergestate.commit: factor out making the list of records
Will aid in testing.
2015-11-17 14:23:26 -08:00
Siddharth Agarwal
9f1990c72b mergestate: move _read() call to read constructor
With this patch, mergestate.clean() will no longer abort when it encounters an
unsupported merge type. However we hold off on testing it until backwards
compatibility is in place.
2015-11-17 14:04:56 -08:00
Siddharth Agarwal
99a292eb8d mergestate: add a constructor that reads state from disk
At the moment it's the same as just creating a new mergestate, but we'll soon
move the _read call out of __init__ and in here.
2015-11-17 13:55:30 -08:00