Commit Graph

482 Commits

Author SHA1 Message Date
Martin von Zweigbergk
c0d62c5e7b merge: perform case-collision checking on final set of actions
When there are multiple common ancestors, we should check for case
collisions only on the resulting actions after bid merge has run. To
do this, move the code until after bid merge.

Move it past _resolvetrivial() too, since that might update
actions. If the remote changed a file and then reverted the change,
while the local side deleted the file and created a new file with a
name that case-folds like the old file, we should fail before this
patch but not after.

Although the changes to the actions caused by _forgetremoved() should
have no effect on case collisions, move it after that, too, so the
next person reading the code won't have to think about it.

Moving it past these blocks of code takes it to the end of
calculateupdates(), so let's even move it outside of the method, so we
also check collisions in actions produced by extensions overriding the
method.
2014-11-14 05:53:04 -08:00
Martin von Zweigbergk
1932d029e7 merge: move cd/dc prompts after largefiles prompts
By moving the cd/dc prompts out of calculateupdates(), we let
largefiles' overridecalculateupdates() so the unresolved values
(i.e. 'cd' or 'dc' rather than 'g', 'r', 'a' and missing). This allows
overridecalculateupdates() to ask the user whether to keep the normal
file or the largefile before the user gets the cd/dc prompt. Whichever
answer the user gives, we make overridecalculateupdates() replace 'cd'
or 'dc' action, saving the user one annoying (and less clear)
question.
2014-12-11 21:21:21 -08:00
Martin von Zweigbergk
d0a73727c6 merge: extract _resolvetrivial() function
We would eventually like to move the resolution of modify/delete and
delete/modify conflicts to the resolve phase. However, we don't want
to move the checks for identical content that were added in
99b29d2bd5ed (merge: before cd/dc prompt, check that changed side
really changed, 2014-12-01). Let's instead move these out to a new
_resolvetrivial() function that processes the actions from
manifestmerge() and replaces any false cd/dc conflicts. The function
will also provide a natural place for us to later add code for
resolving false 'm' conflicts.
2014-12-03 13:50:28 -08:00
Martin von Zweigbergk
b1b9996e9d merge: don't treat 'diverge' and 'renamedelete' like actions
See earlier patch for motivation.
2014-12-09 16:49:55 -08:00
Martin von Zweigbergk
0abe09b21d merge: move dr/rd warning messages out of applyupdates()
As preparation for making 'dr' and 'rd' actions no longer actions,
move the reporting from applyupdates() to its caller update(). This
way we won't have to pass additonal arguments to applyupdates() when
they are no longer actions. Also, the warnings are equally unrelated
to applyupdates() as they are to recordupdates(), as they don't result
in any changes to either the working copy or the dirstate.

See earlier patch for additional motivation.
2014-12-09 14:18:31 -08:00
Martin von Zweigbergk
6ddc19cb79 merge: don't report progress for dr/rd actions
It is easier to reason about certain algorithms in terms of a
file->action mapping than the current action->list-of-files. Bid merge
is already written this way (but with a list of actions per file), and
largefiles' overridecalculateupdates() will also benefit. However,
that requires us to have at most one action per file. That requirement
is currently violated by 'dr' (divergent rename) and 'rd' (rename and
delete) actions, which can exist for the same file as some other
action.

These actions are only used for displaying warnings to the user; they
don't change anything in the working copy or the dirstate. In this
way, they are similar to the 'k' (keep) action. However, they are even
less action-like than 'k' is: 'k' at least describes what to do with
the file ("do nothing"), while 'dr' and 'rd' or only annotations for
files for which there may exist other, "real" actions.

As a first step towards separating these acitons out, stop including
them in the progress output, just like we already exclude the 'k'
action.
2014-12-05 16:13:26 -08:00
Martin von Zweigbergk
72e9071545 merge: make 'keep' message more descriptive
Most merge action messages don't describe the action itself, they
describe the reason the action was taken. The only exeption is the 'k'
action, for which the message is just "keep" and instead there is a
code comment folling it that says "remote unchanged". Let's move that
comment into the merge action message.
2014-12-03 14:03:20 -08:00
Matt Mackall
004a613006 merge with stable 2014-12-05 12:10:56 -06:00
Martin von Zweigbergk
7526f0e8b8 merge: don't overwrite conflicting file in locally renamed directory
When the local side has renamed a directory from a/ to b/ and added a
file b/c in it, and the remote side has added a file a/c, we end up
overwriting the local file b/c with the contents of remote file
a/c. Add a check for this case and use the merge ('m') action in this
case instead of the directory rename get ('dg') action.
2014-12-03 11:02:52 -08:00
Martin von Zweigbergk
24dc017945 merge: don't ignore conflicting file in remote renamed directory
When the remote side has renamed a directory from a/ to b/ and added a
file b/c in it, and the local side has added a file a/c, we end up
moving a/c to b/c without considering the remote version of b/c. Add a
check for this case and use the merge ('m') action in this case
instead of the directory rename ('dm') action.
2014-12-03 10:56:07 -08:00
Martin von Zweigbergk
0483da3f64 merge: duplicate 'if f in copied' into each branch 2014-11-23 15:08:50 -08:00
Martin von Zweigbergk
1f5f9eefce merge: branch code into {n1 and n2, n1, n2} top-level cases
There are three high-level cases that are of interest in
manifestmerge(): 1) The file exists on both sides, 2) The file exists
only on the local side, and 3) The file exists only on the remote
side. Let's make this clearer in the code.

The 'if f in copied' case will be broken up into the two applicable
branches in the next patch.
2014-11-23 14:09:10 -08:00
Martin von Zweigbergk
81df1b38d5 merge: display modify/delete conflict prompts in sorted order
The order is determined by manifest.diff(), which currently is not
sorted. There are currently no tests for this, but we will soon add
some that would be flaky without this patch.
2014-11-26 10:25:27 -08:00
Martin von Zweigbergk
7a9312d969 update: don't overwrite untracked ignored files on update
When looking for untracked files that would conflict with a tracked
file in the target revision (or the remote side of a merge), we
explcitly exclude ignored files. The code was added in f1db75422e70
(merge: refactor unknown file conflict checking, 2012-02-09), but it
seems like only unknown, not ignored, files were considered since the
beginning of time.

Although ignored files are mostly build outputs and backup files, we
should still not overwrite them. Fix by simply removing the explicit
check.
2014-11-16 23:41:44 -08:00
Mads Kiilerich
4c4b1f5ddd merge: before cd/dc prompt, check that changed side really changed
Before, merging would in some cases ask "wrong" questions about
"changed/deleted" conflicts ... and even do it before the resolve phase where
they can be postponed, re"resolved" or answered in bulk operations.

Instead, check that the content of the changed file really did change.

Reading and comparing file content is expensive and should be avoided before
the resolve phase. Prompting the user is however even more expensive. Checking
the content here is thus better.

The 'f in ancestors[0]' should not be necessary but is included to be extra
safe.
2014-12-01 02:30:21 +01:00
Matt Mackall
289d6b53bc merge with stable 2014-12-01 19:34:11 -06:00
Pierre-Yves David
c52ad3f03b manifest: document the extra letter in working copy manifest node
As the second developer to get confused by this in November, I'm adding some
documentation for the next poor soul.
2014-11-26 15:37:01 -08:00
Mads Kiilerich
9389b9fa07 merge: 0 is a valid ancestor different from None
Most internal functions can take either a hash or an integer. Merge did however
not handle 0 as revision 0. Now it does.
2014-11-30 19:26:53 +01:00
Martin von Zweigbergk
bdbe0fa90a merge: use None as filename for base in 'both created' conflicts
Instead of using a file that we know is not in the common ancestor's
maniffest, let's use None. This is safe as the only place that cares
about the value (applyupdates) already checks if the item exists in
the ancestor.
2014-11-24 16:17:02 -08:00
Martin von Zweigbergk
96d97f796c merge: break out "both renamed a -> b" case
We can further limit the scope of the 2-way merge case by breaking out
the case where the file was not created from scratch on both sides but
rather renamed in the same way (and is therefore a 3-way merge). This
involves copying some code, but it makes it clearer which case the
"Note:" in the code refers to.
2014-11-24 16:42:36 -08:00
Martin von Zweigbergk
dd435d36bb merge: separate out "both created" cases
When 'f' is not in 'ma', 'a' will be 'nullid' and all the if/elif
conditions that check whether some one nodeid is equal to 'a' will
fail, and the else-clause will instead apply. We can make that more
explicit by creating a separate 'm' action for the case where 'a' is
'nullid'. While it does mean copying some code, perhaps it makes it a
little clearer which codepaths are possible, and which cases the
"Note:" in the code refers to. It also lets us make the debug action
messages a little more specific.
2014-11-24 16:16:34 -08:00
Martin von Zweigbergk
b78125e6ba merge: indent to prepare for next patch 2014-11-24 16:11:22 -08:00
Martin von Zweigbergk
663d394fe9 merge: remove obsolete check for untracked files in 'dm' action
Since 4a56fba99974 (merge: don't use unknown(), 2012-02-09), untracked
files are no longer included in the manifest diff, so there is no need
to check exclude them when renaming files for directory moves with the
'dm' action.
2014-11-24 09:50:27 -08:00
Martin von Zweigbergk
52b3a1afd7 merge: remove dead assignment in applyupdates() 2014-11-23 23:10:34 -08:00
Martin von Zweigbergk
3e76cdec1c merge: move calculateupdates() before applyupdated()
calculateupdates() happens before applyupdates(), so move it before in
the code. That also moves it close to manifestmerge(), which is a good
location as calculateupdates() is the only caller of manifestmerge().
2014-11-21 13:06:04 -08:00
Martin von Zweigbergk
527ed28755 merge: remove unused variables from _checkcollision() 2014-11-24 11:28:46 -08:00
Martin von Zweigbergk
d69dae068a merge: consistently use single quotes for non-user-facing strings
Because I'm getting tired of searching for both 'O' and "O".
2014-11-20 16:39:32 -08:00
Martin von Zweigbergk
1d09a87f4e merge: remove confusing comment about --force
manifestmerge() has a piece of code that's roughly:

  if not force and different:
      abort
  else:
      # if different: old untracked f may be overwritten and lost
      ...

The comment only talks about what happens when 'different' is true,
and in combination with the if-block above, that must mean that it is
only about what happens when 'force and different'. It seems quite
fine that files are overwritten when 'force' is true, so let's remove
the comment. As it stands, it can easily be interpreted as a TODO
(which is how I interpreted it at first).
2014-11-19 08:50:08 -08:00
Martin von Zweigbergk
f29370d747 update: remove unnecessary check for unknown files with --check
As far as I and the test suite can tell, the checks in manifestmerge()
already report the errors (whether or not --check is given), so we
don't need to call merge.checkunknown(). Since this is the last call
to the method, also remove the method.
2014-11-18 16:14:32 -08:00
Martin von Zweigbergk
edf3f3461a manifestmerge: use already existing fl2 synonym for m2.flags(f)
Probably not a noticeable performance gain, but shortens the code
slightly.
2014-11-14 09:33:28 -08:00
Martin von Zweigbergk
6584c8e690 merge: drop underscore prefix from _checkunknown()
The method has been called from commands.py since 8d9ca2ac2fe8
(update: just merge unknown file collisions, 2012-02-09), so drop the
underscore prefix that suggests that it's private.
2014-11-13 23:12:15 -08:00
Martin von Zweigbergk
9f2b4a3510 manifest: transpose pair of pairs from diff()
It makes more sense for the file nodeids and returned from diff() to
be ((n1,fl1),(n2,fl2)) than ((n1,n2),(fl1,fl2)), so change it to the
former.
2014-10-14 23:18:07 -07:00
Martin von Zweigbergk
a7638ac991 manifest: for diff(), only iterate over files, not flags
From manifest.diff(), we return a dict from filename to pairs of pairs
of file nodeids and flags (values of the form ((n1,n2),(fl1,fl2))). To
create this dict, we currently generate one dict for files (with
(n1,n2) values) and one for flags (with (fl1,fl2) values) and then
join these dicts. Missing files are represented by None and missing
flags by '', but due to the dict joining, the inner pairs themselves
can also be None. The only caller, merge.manifestmerge(), then unpacks
these values while checking for None values.

By inlining the calls to dicthelpers and simplifying it to only
iterate over files (ignoring flags-only differences), we can simplify
life for our caller.
2014-10-14 22:48:44 -07:00
Martin von Zweigbergk
3ccf5a82f8 manifest: repurpose flagsdiff() into (node-and-flag)diff()
The manifestdict class already has a method for diff flags between two
manifests (presumably because there is no full access to the private
_flags field). The only caller is merge.manifestmerge(), which also
wants a diff of files between the same manifests. Let's combine the
code for diffing files and flags into a single method on
manifestdict. This puts all the manifest diffing in one place and will
allow for further simplification. It might also be useful for it to be
encapsulated in manifestdict if we later decide to to shard
manifests. The docstring is intentionally unclear about missing
entries for now.
2014-10-14 17:09:16 -07:00
Matt Mackall
0327807819 merge: add merge.graft helper
This will help unify all the open-coded graft/rebase operations.
2014-10-13 17:12:12 -05:00
Martin von Zweigbergk
545877b86f merge: make error message consistent with other commands
If a merge is attempted when another merge is already ongoing, we give
the message "outstanding uncommitted merges". Many other commands
(such as backout, rebase, histedit) give the same message in singular
form. Since the singular form also seems to make more sense, let's use
that for 'hg merge' as well.
2014-10-08 14:16:53 -07:00
Pierre-Yves David
04745ea203 merge.update: use first instead of direct indexing
This makes it compatible with all smartset classes.
2014-10-07 00:41:58 -07:00
Mads Kiilerich
031ab4d02f merge: mute the status message when bid merge kicks in
Bid merge is now the default and it is not necessary to tell the user that an
experimental feature kicked in.

(It could however still be relevant to get a notice that it is one of the rare
criss-cross merge situations so the user is warned that the situation is more
tricky than usual.)
2014-10-01 03:42:00 +02:00
Mads Kiilerich
9ecbab9de8 merge: use bid merge by default (BC)
In most cases merges will work exactly as before.

The only difference is in criss-cross merge situations where there is multiple
ancestors. Instead of picking an more or less arbitrary ancestor, it will
consider both ancestors and pick the best bids.

Bid merge can be disabled with --config merge.preferancestor='!'.
2014-10-01 03:41:11 +02:00
Durham Goode
a5a69f0001 dirstate: wrap setparent calls with begin/endparentchange (issue4353)
This wraps all the locations of dirstate.setparent with the appropriate
begin/endparentchange calls. This will prevent exceptions during those calls
from causing incoherent dirstates (issue4353).
2014-09-05 11:36:20 -07:00
Matt Mackall
92e0debc2b merge with stable 2014-08-15 11:48:05 -05:00
Mads Kiilerich
5d377a8588 cleanup: avoid local vars shadowing imports
This will mute some pyflakes "import ... shadowed by loop variable" warnings.
2014-08-15 16:20:47 +02:00
Mads Kiilerich
26f83c4483 merge: show the scary multiple ancestor hint for merges only, not for updates
Updates with uncommited changes will always only have one ancestor - the parent
revision. Updates between existing revision should (and will) always give the
same result no matter which ancestor is used. The warning is thus only relevant
when doing a "real" merge.
2014-08-15 02:39:01 +02:00
Mads Kiilerich
609d92f9c5 merge: fix stupid indentation left over from previous refactorings 2014-05-02 01:09:14 +02:00
Mads Kiilerich
cb358d8d03 merge: use separate lists for each action type
This replaces the grand unified action list that had multiple action types as
tuples in one big list. That list was iterated multiple times just to find
actions of a specific type. This data model also made some code more
convoluted than necessary.

Instead we now store actions as a tuple of lists. Using multiple lists gives a
bit of cut'n'pasted code but also enables other optimizations.

This patch uses 'if True:' to preserve indentations and help reviewing. It also
limits the number of conflicts with other pending patches. It can trivially be
cleaned up later.
2014-02-28 02:25:58 +01:00
Durham Goode
0ac70cfdb2 merge: add labels parameter from merge.update to filemerge
Adds a labels function parameter to all the functions between merge.update and
filemerge.filemerge. This will allow commands like rebase to specify custom
marker labels.
2014-05-08 16:54:23 -07:00
Mads Kiilerich
e967712b1f merge: separate worker functions for batch remove and batch get
The old code had one function that could do 2 different things. First,
is was called a bunch of times to do one thing. Next, it was called a
bunch of times to do the other thing. That gave unnecessary complexity
and a dispatch overhead. Having separate functions is "obviously" better
than having a function that can do two things, depending on its parameters.
It also prepares the code for the next refactorings.
2014-05-09 12:01:56 +02:00
Mads Kiilerich
473137c772 merge: change debug logging - test output changes but no real changes
Preparing for action list split-up, making sure the final change don't have any
test changes.

The patch moves debug statements around without really changing anything.
Arguably, it temporarily makes the code worse. The only justification is that
it makes it easier to review the test changes ... and in the end the big change
will not change test output at all.

The changes to test output are due to changes in the ordering of debug output.
That is mainly because we now do the debug logging for files when we actually
process them. Files are also processed in a slightly different but still
correct order. It is now primarily ordered by action type, secondarily by
filename.

The patch introduces some redundancy. Some of it will be removed again, some of
it will in the end help code readability and efficiency. It is possible that we
later on could introduce a "process this action list and do some logging and
progress reporting and apply this function".

The "preserving X for resolve" debug statements will only have single space
indentation. It will no longer have a leading single space indented "f: msg ->
m" message. Having this message double indented would thus no longer make
sense.

The bid actions will temporarily be sorted using a custom sort key that happens
to match the sort order the simplified code will have in the end.
2014-04-22 02:10:25 +02:00
Mads Kiilerich
b70986433b merge: move constant assignments a bit and use them more 2014-05-15 02:14:59 +02:00
Mads Kiilerich
43db2a4aa5 merge: change priority / ordering of merge actions
The ordering of actions matters. Normal file system semantics is that files
have to be removed before a directory with the same name can be created.

Before the first ordering key was to have 'r' and 'f' actions come first,
secondary key was the filename.

Because of future refactorings we want to consistently have all action types
(with a sensible priority) as separate first keys. Grouped by action type, we
sort by filename.

Not processing in strict filename order could give worse performance,
especially on spinning disks. That is however primarily an issue in the cases
where "all" actions are of the same kind and will be grouped together anyway.
2014-05-02 01:09:14 +02:00