mercurial/merge.py
author Joel Rosdahl <joel@rosdahl.net>
Thu, 06 Mar 2008 22:23:26 +0100
changeset 6211 f89fd07fc51d
parent 6003 7855b88ba838
child 6242 a375ffc2aa1b
permissions -rw-r--r--
Expand import * to allow Pyflakes to find problems
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# merge.py - directory-level update/merge handling for Mercurial
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
4635
63b9d2deed48 Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4633
diff changeset
     3
# Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
6211
f89fd07fc51d Expand import * to allow Pyflakes to find problems
Joel Rosdahl <joel@rosdahl.net>
parents: 6003
diff changeset
     8
from node import nullid, nullrev
3891
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3877
diff changeset
     9
from i18n import _
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents: 5857
diff changeset
    10
import errno, util, os, heapq, filemerge
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    11
3312
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
    12
def checkunknown(wctx, mctx):
3315
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
    13
    "check for collisions between unknown files and files in mctx"
3312
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
    14
    man = mctx.manifest()
3218
8d4855fd9d7b merge: use new working context object in update
Matt Mackall <mpm@selenic.com>
parents: 3212
diff changeset
    15
    for f in wctx.unknown():
3312
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
    16
        if f in man:
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
    17
            if mctx.filectx(f).cmp(wctx.filectx(f).data()):
5670
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
    18
                raise util.Abort(_("untracked file in working directory differs"
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
    19
                                   " from file in requested revision: '%s'")
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
    20
                                 % f)
3107
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    21
3785
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
    22
def checkcollision(mctx):
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
    23
    "check for case folding collisions in the destination context"
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
    24
    folded = {}
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
    25
    for fn in mctx.manifest():
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
    26
        fold = fn.lower()
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
    27
        if fold in folded:
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
    28
            raise util.Abort(_("case-folding collision between %s and %s")
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
    29
                             % (fn, folded[fold]))
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
    30
        folded[fold] = fn
6398ff7cb705 imported patch collision
Matt Mackall <mpm@selenic.com>
parents: 3773
diff changeset
    31
3312
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
    32
def forgetremoved(wctx, mctx):
3107
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    33
    """
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    34
    Forget removed files
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    35
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    36
    If we're jumping between revisions (as opposed to merging), and if
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    37
    neither the working directory nor the target rev has the file,
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    38
    then we need to remove it from the dirstate, to prevent the
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    39
    dirstate from listing the file when it is no longer in the
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    40
    manifest.
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    41
    """
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    42
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    43
    action = []
3312
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
    44
    man = mctx.manifest()
3218
8d4855fd9d7b merge: use new working context object in update
Matt Mackall <mpm@selenic.com>
parents: 3212
diff changeset
    45
    for f in wctx.deleted() + wctx.removed():
3312
c5075ad5e3e9 merge: use contexts in checkunknown and forgetremoved
Matt Mackall <mpm@selenic.com>
parents: 3311
diff changeset
    46
        if f not in man:
3107
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    47
            action.append((f, "f"))
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    48
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    49
    return action
3bd05ad67f45 merge: pull manifest checks and updates into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3106
diff changeset
    50
3371
8c36b33a27c7 merge: turn followcopies on by default
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
    51
def findcopies(repo, m1, m2, ma, limit):
3153
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
    52
    """
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
    53
    Find moves and copies between m1 and m2 back to limit linkrev
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
    54
    """
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
    55
4400
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
    56
    def nonoverlap(d1, d2, d3):
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
    57
        "Return list of elements in d1 not in d2 or d3"
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
    58
        l = [d for d in d1 if d not in d3 and d not in d2]
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
    59
        l.sort()
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
    60
        return l
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
    61
4397
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    62
    def dirname(f):
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    63
        s = f.rfind("/")
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    64
        if s == -1:
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    65
            return ""
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    66
        return f[:s]
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    67
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    68
    def dirs(files):
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    69
        d = {}
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    70
        for f in files:
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    71
            f = dirname(f)
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    72
            while f not in d:
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    73
                d[f] = True
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    74
                f = dirname(f)
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    75
        return d
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
    76
4416
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
    77
    wctx = repo.workingctx()
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
    78
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
    79
    def makectx(f, n):
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
    80
        if len(n) == 20:
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
    81
            return repo.filectx(f, fileid=n)
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
    82
        return wctx.filectx(f)
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
    83
    ctx = util.cachefunc(makectx)
bb1800a7d7e1 merge: fix spurious merges for copies in linear updates
Matt Mackall <mpm@selenic.com>
parents: 4400
diff changeset
    84
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
    85
    def findold(fctx):
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
    86
        "find files that path was copied from, back to linkrev limit"
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
    87
        old = {}
4350
8aee687f0214 merge: fix quadratic behavior in find-copies
Matt Mackall <mpm@selenic.com>
parents: 4304
diff changeset
    88
        seen = {}
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
    89
        orig = fctx.path()
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
    90
        visit = [fctx]
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
    91
        while visit:
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
    92
            fc = visit.pop()
4350
8aee687f0214 merge: fix quadratic behavior in find-copies
Matt Mackall <mpm@selenic.com>
parents: 4304
diff changeset
    93
            s = str(fc)
8aee687f0214 merge: fix quadratic behavior in find-copies
Matt Mackall <mpm@selenic.com>
parents: 4304
diff changeset
    94
            if s in seen:
8aee687f0214 merge: fix quadratic behavior in find-copies
Matt Mackall <mpm@selenic.com>
parents: 4304
diff changeset
    95
                continue
8aee687f0214 merge: fix quadratic behavior in find-copies
Matt Mackall <mpm@selenic.com>
parents: 4304
diff changeset
    96
            seen[s] = 1
3875
c0a12e6441a5 Fix copy detection corner case
Matt Mackall <mpm@selenic.com>
parents: 3862
diff changeset
    97
            if fc.path() != orig and fc.path() not in old:
c0a12e6441a5 Fix copy detection corner case
Matt Mackall <mpm@selenic.com>
parents: 3862
diff changeset
    98
                old[fc.path()] = 1
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
    99
            if fc.rev() < limit:
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   100
                continue
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   101
            visit += fc.parents()
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   102
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   103
        old = old.keys()
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   104
        old.sort()
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   105
        return old
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   106
4400
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
   107
    copy = {}
84cd52b48f94 merge: reorganize some hunks in findcopies
Matt Mackall <mpm@selenic.com>
parents: 4399
diff changeset
   108
    fullcopy = {}
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   109
    diverge = {}
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   110
4884
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
   111
    def checkcopies(c, man, aman):
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   112
        '''check possible copies for filectx c'''
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   113
        for of in findold(c):
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   114
            fullcopy[c.path()] = of # remember for dir rename detection
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   115
            if of not in man: # original file not in other manifest?
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   116
                if of in ma:
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   117
                    diverge.setdefault(of, []).append(c.path())
4304
4787e2b0dd03 merge: fix a bug where copies were ignored
Matt Mackall <mpm@selenic.com>
parents: 4179
diff changeset
   118
                continue
4884
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
   119
            # if the original file is unchanged on the other branch,
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
   120
            # no merge needed
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
   121
            if man[of] == aman.get(of):
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
   122
                continue
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   123
            c2 = ctx(of, man[of])
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   124
            ca = c.ancestor(c2)
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   125
            if not ca: # unrelated?
4304
4787e2b0dd03 merge: fix a bug where copies were ignored
Matt Mackall <mpm@selenic.com>
parents: 4179
diff changeset
   126
                continue
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   127
            # named changed on only one side?
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   128
            if ca.path() == c.path() or ca.path() == c2.path():
5433
f9b0e4f023c4 findcopies: fix rename bug
Matt Mackall <mpm@selenic.com>
parents: 5096
diff changeset
   129
                if c == ca and c2 == ca: # no merge needed, ignore copy
4304
4787e2b0dd03 merge: fix a bug where copies were ignored
Matt Mackall <mpm@selenic.com>
parents: 4179
diff changeset
   130
                    continue
3732
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   131
                copy[c.path()] = of
ffe9fef84801 merge: pull findcopies helpers inside, refactor checkpair to checkcopies
Matt Mackall <mpm@selenic.com>
parents: 3731
diff changeset
   132
3371
8c36b33a27c7 merge: turn followcopies on by default
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
   133
    if not repo.ui.configbool("merge", "followcopies", True):
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   134
        return {}, {}
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
   135
3160
1839e6e91c3a findcopies: shortcut for empty working dir
Matt Mackall <mpm@selenic.com>
parents: 3155
diff changeset
   136
    # avoid silly behavior for update from empty dir
3731
b4af5f92e04b merge: move check for empty ancestor into findcopies
Matt Mackall <mpm@selenic.com>
parents: 3730
diff changeset
   137
    if not m1 or not m2 or not ma:
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   138
        return {}, {}
3160
1839e6e91c3a findcopies: shortcut for empty working dir
Matt Mackall <mpm@selenic.com>
parents: 3155
diff changeset
   139
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   140
    repo.ui.debug(_("  searching for copies back to rev %d\n") % limit)
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   141
3371
8c36b33a27c7 merge: turn followcopies on by default
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
   142
    u1 = nonoverlap(m1, m2, ma)
8c36b33a27c7 merge: turn followcopies on by default
Matt Mackall <mpm@selenic.com>
parents: 3316
diff changeset
   143
    u2 = nonoverlap(m2, m1, ma)
3153
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
   144
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   145
    if u1:
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   146
        repo.ui.debug(_("  unmatched files in local:\n   %s\n")
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   147
                      % "\n   ".join(u1))
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   148
    if u2:
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   149
        repo.ui.debug(_("  unmatched files in other:\n   %s\n")
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   150
                      % "\n   ".join(u2))
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   151
3153
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
   152
    for f in u1:
4884
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
   153
        checkcopies(ctx(f, m1[f]), m2, ma)
3153
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
   154
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
   155
    for f in u2:
4884
931f901ab811 merge: fix unnecessary rename merges on linear update (issue631)
Matt Mackall <mpm@selenic.com>
parents: 4819
diff changeset
   156
        checkcopies(ctx(f, m2[f]), m1, ma)
3153
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
   157
5857
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
   158
    diverge2 = {}
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   159
    for of, fl in diverge.items():
5857
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
   160
        if len(fl) == 1:
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
   161
            del diverge[of] # not actually divergent
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
   162
        else:
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
   163
            diverge2.update(dict.fromkeys(fl)) # reverse map for below
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   164
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   165
    if fullcopy:
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   166
        repo.ui.debug(_("  all copies found (* = to merge, ! = divergent):\n"))
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   167
        for f in fullcopy:
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   168
            note = ""
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   169
            if f in copy: note += "*"
5857
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
   170
            if f in diverge2: note += "!"
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   171
            repo.ui.debug(_("   %s -> %s %s\n") % (f, fullcopy[f], note))
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   172
5857
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
   173
    del diverge2
c704b03884ef merge: add a bit more sanity to divergent copy checks
Matt Mackall <mpm@selenic.com>
parents: 5708
diff changeset
   174
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   175
    if not fullcopy or not repo.ui.configbool("merge", "followdirs", True):
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   176
        return copy, diverge
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   177
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   178
    repo.ui.debug(_("  checking for directory renames\n"))
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   179
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   180
    # generate a directory move map
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   181
    d1, d2 = dirs(m1), dirs(m2)
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   182
    invalid = {}
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   183
    dirmove = {}
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   184
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   185
    # examine each file copy for a potential directory move, which is
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   186
    # when all the files in a directory are moved to a new directory
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   187
    for dst, src in fullcopy.items():
4397
9fe267f77f56 merge: fix a bug detecting directory moves
Matt Mackall <mpm@selenic.com>
parents: 4396
diff changeset
   188
        dsrc, ddst = dirname(src), dirname(dst)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   189
        if dsrc in invalid:
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   190
            # already seen to be uninteresting
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   191
            continue
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   192
        elif dsrc in d1 and ddst in d1:
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   193
            # directory wasn't entirely moved locally
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   194
            invalid[dsrc] = True
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   195
        elif dsrc in d2 and ddst in d2:
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   196
            # directory wasn't entirely moved remotely
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   197
            invalid[dsrc] = True
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   198
        elif dsrc in dirmove and dirmove[dsrc] != ddst:
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   199
            # files from the same directory moved to two different places
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   200
            invalid[dsrc] = True
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   201
        else:
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   202
            # looks good so far
4115
c95060a5391a merge: fix renaming of subdirectories under renamed directories
Matt Mackall <mpm@selenic.com>
parents: 3875
diff changeset
   203
            dirmove[dsrc + "/"] = ddst + "/"
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   204
4398
3b7e284b8f28 merge: expand and simplify the invalid handling for directory moves
Matt Mackall <mpm@selenic.com>
parents: 4397
diff changeset
   205
    for i in invalid:
3b7e284b8f28 merge: expand and simplify the invalid handling for directory moves
Matt Mackall <mpm@selenic.com>
parents: 4397
diff changeset
   206
        if i in dirmove:
3b7e284b8f28 merge: expand and simplify the invalid handling for directory moves
Matt Mackall <mpm@selenic.com>
parents: 4397
diff changeset
   207
            del dirmove[i]
3b7e284b8f28 merge: expand and simplify the invalid handling for directory moves
Matt Mackall <mpm@selenic.com>
parents: 4397
diff changeset
   208
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   209
    del d1, d2, invalid
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   210
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   211
    if not dirmove:
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   212
        return copy, diverge
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   213
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   214
    for d in dirmove:
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   215
        repo.ui.debug(_("  dir %s -> %s\n") % (d, dirmove[d]))
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   216
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   217
    # check unaccounted nonoverlapping files against directory moves
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   218
    for f in u1 + u2:
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   219
        if f not in fullcopy:
4115
c95060a5391a merge: fix renaming of subdirectories under renamed directories
Matt Mackall <mpm@selenic.com>
parents: 3875
diff changeset
   220
            for d in dirmove:
c95060a5391a merge: fix renaming of subdirectories under renamed directories
Matt Mackall <mpm@selenic.com>
parents: 3875
diff changeset
   221
                if f.startswith(d):
4396
c04c96504a12 merge: clarify the findcopies code
Matt Mackall <mpm@selenic.com>
parents: 4350
diff changeset
   222
                    # new file added in a directory that was moved, move it
4115
c95060a5391a merge: fix renaming of subdirectories under renamed directories
Matt Mackall <mpm@selenic.com>
parents: 3875
diff changeset
   223
                    copy[f] = dirmove[d] + f[len(d):]
5371
17ed9b9a0d03 merge: add debug diagnostics for findcopies
Matt Mackall <mpm@selenic.com>
parents: 5210
diff changeset
   224
                    repo.ui.debug(_("  file %s -> %s\n") % (f, copy[f]))
4115
c95060a5391a merge: fix renaming of subdirectories under renamed directories
Matt Mackall <mpm@selenic.com>
parents: 3875
diff changeset
   225
                    break
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   226
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   227
    return copy, diverge
3153
c82ea81d6850 Add core copy detection algorithm
Matt Mackall <mpm@selenic.com>
parents: 3121
diff changeset
   228
5096
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   229
def symmetricdifference(repo, rev1, rev2):
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   230
    """symmetric difference of the sets of ancestors of rev1 and rev2
5433
f9b0e4f023c4 findcopies: fix rename bug
Matt Mackall <mpm@selenic.com>
parents: 5096
diff changeset
   231
5096
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   232
    I.e. revisions that are ancestors of rev1 or rev2, but not both.
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   233
    """
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   234
    # basic idea:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   235
    # - mark rev1 and rev2 with different colors
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   236
    # - walk the graph in topological order with the help of a heap;
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   237
    #   for each revision r:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   238
    #     - if r has only one color, we want to return it
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   239
    #     - add colors[r] to its parents
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   240
    #
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   241
    # We keep track of the number of revisions in the heap that
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   242
    # we may be interested in.  We stop walking the graph as soon
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   243
    # as this number reaches 0.
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   244
    WHITE = 1
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   245
    BLACK = 2
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   246
    ALLCOLORS = WHITE | BLACK
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   247
    colors = {rev1: WHITE, rev2: BLACK}
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   248
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   249
    cl = repo.changelog
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   250
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   251
    visit = [-rev1, -rev2]
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   252
    heapq.heapify(visit)
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   253
    n_wanted = len(visit)
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   254
    ret = []
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   255
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   256
    while n_wanted:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   257
        r = -heapq.heappop(visit)
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   258
        wanted = colors[r] != ALLCOLORS
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   259
        n_wanted -= wanted
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   260
        if wanted:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   261
            ret.append(r)
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   262
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   263
        for p in cl.parentrevs(r):
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   264
            if p == nullrev:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   265
                continue
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   266
            if p not in colors:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   267
                # first time we see p; add it to visit
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   268
                n_wanted += wanted
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   269
                colors[p] = colors[r]
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   270
                heapq.heappush(visit, -p)
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   271
            elif colors[p] != ALLCOLORS and colors[p] != colors[r]:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   272
                # at first we thought we wanted p, but now
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   273
                # we know we don't really want it
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   274
                n_wanted -= 1
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   275
                colors[p] |= colors[r]
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   276
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   277
        del colors[r]
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   278
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   279
    return ret
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   280
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
   281
def manifestmerge(repo, p1, p2, pa, overwrite, partial):
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   282
    """
3315
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   283
    Merge p1 and p2 with ancestor ma and generate merge action list
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   284
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   285
    overwrite = whether we clobber working files
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   286
    partial = function to filter file lists
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   287
    """
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   288
3314
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
   289
    repo.ui.note(_("resolving manifests\n"))
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
   290
    repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
   291
    repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
   292
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
   293
    m1 = p1.manifest()
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
   294
    m2 = p2.manifest()
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
   295
    ma = pa.manifest()
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
   296
    backwards = (pa == p2)
3314
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
   297
    action = []
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
   298
    copy = {}
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   299
    diverge = {}
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
   300
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
   301
    def fmerge(f, f2=None, fa=None):
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   302
        """merge flags"""
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
   303
        if not f2:
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
   304
            f2 = f
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
   305
            fa = f
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   306
        a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   307
        if m == n: # flags agree
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   308
            return m # unchanged
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   309
        if m and n: # flags are set but don't agree
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   310
            if not a: # both differ from parent
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   311
                r = repo.ui.prompt(
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   312
                    _(" conflicting flags for %s\n"
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   313
                      "(n)one, e(x)ec or sym(l)ink?") % f, "[nxl]", "n")
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   314
                return r != "n" and r or ''
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   315
            if m == a:
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   316
                return n # changed from m to n
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   317
            return m # changed from n to m
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   318
        if m and m != a: # changed from a to m
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   319
            return m
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   320
        if n and n != a: # changed from a to n
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   321
            return n
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   322
        return '' # flag was cleared
3118
5644a05a608c merge: simplify exec flag handling
Matt Mackall <mpm@selenic.com>
parents: 3117
diff changeset
   323
3307
f009a6f12a59 merge: swap file and mode args for act()
Matt Mackall <mpm@selenic.com>
parents: 3306
diff changeset
   324
    def act(msg, m, f, *args):
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
   325
        repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
3121
2ef0b3aae186 merge: simplify actions with helper function
Matt Mackall <mpm@selenic.com>
parents: 3120
diff changeset
   326
        action.append((f, m) + args)
2ef0b3aae186 merge: simplify actions with helper function
Matt Mackall <mpm@selenic.com>
parents: 3120
diff changeset
   327
3731
b4af5f92e04b merge: move check for empty ancestor into findcopies
Matt Mackall <mpm@selenic.com>
parents: 3730
diff changeset
   328
    if not (backwards or overwrite):
5096
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   329
        rev1 = p1.rev()
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   330
        if rev1 is None:
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   331
            # p1 is a workingctx
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   332
            rev1 = p1.parents()[0].rev()
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   333
        limit = min(symmetricdifference(repo, rev1, p2.rev()))
ad6b97132b81 merge: fix a copy detection bug (issue672)
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5059
diff changeset
   334
        copy, diverge = findcopies(repo, m1, m2, ma, limit)
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   335
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   336
    for of, fl in diverge.items():
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   337
        act("divergent renames", "dr", of, fl)
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   338
3730
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   339
    copied = dict.fromkeys(copy.values())
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
   340
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   341
    # Compare manifests
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   342
    for f, n in m1.iteritems():
3248
751840e739a1 merge: reduce manifest copying
Matt Mackall <mpm@selenic.com>
parents: 3247
diff changeset
   343
        if partial and not partial(f):
751840e739a1 merge: reduce manifest copying
Matt Mackall <mpm@selenic.com>
parents: 3247
diff changeset
   344
            continue
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   345
        if f in m2:
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   346
            if overwrite or backwards:
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   347
                rflags = m2.flags(f)
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   348
            else:
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   349
                rflags = fmerge(f)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   350
            # are files different?
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   351
            if n != m2[f]:
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   352
                a = ma.get(f, nullid)
5700
9cedc3fbbebb merge: simplify merge tests, fix exec flag bug
Matt Mackall <mpm@selenic.com>
parents: 5695
diff changeset
   353
                # are we clobbering?
9cedc3fbbebb merge: simplify merge tests, fix exec flag bug
Matt Mackall <mpm@selenic.com>
parents: 5695
diff changeset
   354
                if overwrite:
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   355
                    act("clobbering", "g", f, rflags)
5700
9cedc3fbbebb merge: simplify merge tests, fix exec flag bug
Matt Mackall <mpm@selenic.com>
parents: 5695
diff changeset
   356
                # or are we going back in time and clean?
9cedc3fbbebb merge: simplify merge tests, fix exec flag bug
Matt Mackall <mpm@selenic.com>
parents: 5695
diff changeset
   357
                elif backwards and not n[20:]:
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   358
                    act("reverting", "g", f, rflags)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   359
                # are both different from the ancestor?
5700
9cedc3fbbebb merge: simplify merge tests, fix exec flag bug
Matt Mackall <mpm@selenic.com>
parents: 5695
diff changeset
   360
                elif n != a and m2[f] != a:
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   361
                    act("versions differ", "m", f, f, f, rflags, False)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   362
                # is remote's version newer?
5700
9cedc3fbbebb merge: simplify merge tests, fix exec flag bug
Matt Mackall <mpm@selenic.com>
parents: 5695
diff changeset
   363
                elif m2[f] != a:
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   364
                    act("remote is newer", "g", f, rflags)
3113
d1d1cd5b9484 merge: eliminate confusing queued variable
Matt Mackall <mpm@selenic.com>
parents: 3112
diff changeset
   365
                # local is newer, not overwrite, check mode bits
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   366
                elif m1.flags(f) != rflags:
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   367
                    act("update permissions", "e", f, rflags)
3113
d1d1cd5b9484 merge: eliminate confusing queued variable
Matt Mackall <mpm@selenic.com>
parents: 3112
diff changeset
   368
            # contents same, check mode bits
5708
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   369
            elif m1.flags(f) != rflags:
f6bf89722e29 merge: add flag merging intelligence
Matt Mackall <mpm@selenic.com>
parents: 5704
diff changeset
   370
                act("update permissions", "e", f, rflags)
3730
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   371
        elif f in copied:
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   372
            continue
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
   373
        elif f in copy:
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
   374
            f2 = copy[f]
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   375
            if f2 not in m2: # directory rename
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   376
                act("remote renamed directory to " + f2, "d",
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   377
                    f, None, f2, m1.flags(f))
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   378
            elif f2 in m1: # case 2 A,B/B/B
3730
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   379
                act("local copied to " + f2, "m",
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   380
                    f, f2, f, fmerge(f, f2, f2), False)
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   381
            else: # case 4,21 A/B/B
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   382
                act("local moved to " + f2, "m",
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   383
                    f, f2, f, fmerge(f, f2, f2), False)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   384
        elif f in ma:
3117
7a635ef25132 merge: simplify tests for local changed/remote deleted
Matt Mackall <mpm@selenic.com>
parents: 3116
diff changeset
   385
            if n != ma[f] and not overwrite:
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
   386
                if repo.ui.prompt(
5670
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
   387
                    _(" local changed %s which remote deleted\n"
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
   388
                      "use (c)hanged version or (d)elete?") % f,
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
   389
                    _("[cd]"), _("c")) == _("d"):
3307
f009a6f12a59 merge: swap file and mode args for act()
Matt Mackall <mpm@selenic.com>
parents: 3306
diff changeset
   390
                    act("prompt delete", "r", f)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   391
            else:
3307
f009a6f12a59 merge: swap file and mode args for act()
Matt Mackall <mpm@selenic.com>
parents: 3306
diff changeset
   392
                act("other deleted", "r", f)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   393
        else:
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   394
            # file is created on branch or in working directory
3120
1c1e59aac82a merge: simplify local created logic
Matt Mackall <mpm@selenic.com>
parents: 3119
diff changeset
   395
            if (overwrite and n[20:] != "u") or (backwards and not n[20:]):
3307
f009a6f12a59 merge: swap file and mode args for act()
Matt Mackall <mpm@selenic.com>
parents: 3306
diff changeset
   396
                act("remote deleted", "r", f)
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   397
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   398
    for f, n in m2.iteritems():
3248
751840e739a1 merge: reduce manifest copying
Matt Mackall <mpm@selenic.com>
parents: 3247
diff changeset
   399
        if partial and not partial(f):
751840e739a1 merge: reduce manifest copying
Matt Mackall <mpm@selenic.com>
parents: 3247
diff changeset
   400
            continue
751840e739a1 merge: reduce manifest copying
Matt Mackall <mpm@selenic.com>
parents: 3247
diff changeset
   401
        if f in m1:
751840e739a1 merge: reduce manifest copying
Matt Mackall <mpm@selenic.com>
parents: 3247
diff changeset
   402
            continue
3729
581d20773326 merge: add copied hash to simplify copy logic
Matt Mackall <mpm@selenic.com>
parents: 3728
diff changeset
   403
        if f in copied:
581d20773326 merge: add copied hash to simplify copy logic
Matt Mackall <mpm@selenic.com>
parents: 3728
diff changeset
   404
            continue
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
   405
        if f in copy:
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
   406
            f2 = copy[f]
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   407
            if f2 not in m1: # directory rename
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   408
                act("local renamed directory to " + f2, "d",
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   409
                    None, f, f2, m2.flags(f))
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   410
            elif f2 in m2: # rename case 1, A/A,B/A
3730
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   411
                act("remote copied to " + f, "m",
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   412
                    f2, f, f, fmerge(f2, f, f2), False)
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   413
            else: # case 3,20 A/B/A
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   414
                act("remote moved to " + f, "m",
d377f8d25662 merge: only store one direction of copies in the copy map
Matt Mackall <mpm@selenic.com>
parents: 3729
diff changeset
   415
                    f2, f, f, fmerge(f2, f, f2), True)
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
   416
        elif f in ma:
3116
920f54a2249e merge: more simplification of m2 manifest scanning
Matt Mackall <mpm@selenic.com>
parents: 3115
diff changeset
   417
            if overwrite or backwards:
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   418
                act("recreating", "g", f, m2.flags(f))
3116
920f54a2249e merge: more simplification of m2 manifest scanning
Matt Mackall <mpm@selenic.com>
parents: 3115
diff changeset
   419
            elif n != ma[f]:
3295
72d1e521da77 merge: use contexts for manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3292
diff changeset
   420
                if repo.ui.prompt(
5670
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
   421
                    _("remote changed %s which local deleted\n"
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
   422
                      "use (c)hanged version or leave (d)eleted?") % f,
840e2b315c1f Fix misleading error and prompts during update/merge (issue556)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5489
diff changeset
   423
                    _("[cd]"), _("c")) == _("c"):
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   424
                    act("prompt recreating", "g", f, m2.flags(f))
3115
bb74f809bc95 merge: reorder tests on m2 items in manifestmerge
Matt Mackall <mpm@selenic.com>
parents: 3114
diff changeset
   425
        else:
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   426
            act("remote created", "g", f, m2.flags(f))
3105
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   427
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   428
    return action
7c7469d41ade merge: pull manifest comparison out into separate function
Matt Mackall <mpm@selenic.com>
parents: 3104
diff changeset
   429
3297
69b9471f26bb merge: pass contexts to applyupdates
Matt Mackall <mpm@selenic.com>
parents: 3296
diff changeset
   430
def applyupdates(repo, action, wctx, mctx):
3315
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   431
    "apply the merge action list to the working directory"
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   432
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   433
    updated, merged, removed, unresolved = 0, 0, 0, 0
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   434
    action.sort()
5042
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
   435
    # prescan for copy/renames
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
   436
    for a in action:
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
   437
        f, m = a[:2]
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
   438
        if m == 'm': # merge
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
   439
            f2, fd, flags, move = a[2:]
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
   440
            if f != fd:
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
   441
                repo.ui.debug(_("copying %s to %s\n") % (f, fd))
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
   442
                repo.wwrite(fd, repo.wread(f), flags)
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
   443
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5060
diff changeset
   444
    audit_path = util.path_auditor(repo.root)
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5060
diff changeset
   445
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   446
    for a in action:
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   447
        f, m = a[:2]
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   448
        if f and f[0] == "/":
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   449
            continue
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   450
        if m == "r": # remove
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   451
            repo.ui.note(_("removing %s\n") % f)
5158
d316124ebbea Make audit_path more stringent.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5060
diff changeset
   452
            audit_path(f)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   453
            try:
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   454
                util.unlink(repo.wjoin(f))
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   455
            except OSError, inst:
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   456
                if inst.errno != errno.ENOENT:
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   457
                    repo.ui.warn(_("update failed to remove %s: %s!\n") %
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   458
                                 (f, inst.strerror))
3673
eb0b4a2d70a9 white space and line break cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3618
diff changeset
   459
            removed += 1
3308
ecc1bf27378c merge: unify merge and copy actions
Matt Mackall <mpm@selenic.com>
parents: 3307
diff changeset
   460
        elif m == "m": # merge
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   461
            f2, fd, flags, move = a[2:]
6003
7855b88ba838 filemerge: pull file-merging code into its own module
Matt Mackall <mpm@selenic.com>
parents: 5857
diff changeset
   462
            r = filemerge.filemerge(repo, f, fd, f2, wctx, mctx)
3400
d2b55e3c4e25 merge: if filemerge skips merge, report as updated
Matt Mackall <mpm@selenic.com>
parents: 3372
diff changeset
   463
            if r > 0:
3249
f05c182430a0 merge: add rename following
Matt Mackall <mpm@selenic.com>
parents: 3248
diff changeset
   464
                unresolved += 1
3309
e8be5942335d merge: pull file copy/move out of filemerge
Matt Mackall <mpm@selenic.com>
parents: 3308
diff changeset
   465
            else:
3400
d2b55e3c4e25 merge: if filemerge skips merge, report as updated
Matt Mackall <mpm@selenic.com>
parents: 3372
diff changeset
   466
                if r is None:
d2b55e3c4e25 merge: if filemerge skips merge, report as updated
Matt Mackall <mpm@selenic.com>
parents: 3372
diff changeset
   467
                    updated += 1
d2b55e3c4e25 merge: if filemerge skips merge, report as updated
Matt Mackall <mpm@selenic.com>
parents: 3372
diff changeset
   468
                else:
d2b55e3c4e25 merge: if filemerge skips merge, report as updated
Matt Mackall <mpm@selenic.com>
parents: 3372
diff changeset
   469
                    merged += 1
5704
5049bbf988e1 merge: use util.set_flags
Matt Mackall <mpm@selenic.com>
parents: 5700
diff changeset
   470
            util.set_flags(repo.wjoin(fd), flags)
5059
8d9bdcbb2b18 merge: avoid double deletion mentioned in issue636
Matt Mackall <mpm@selenic.com>
parents: 5042
diff changeset
   471
            if f != fd and move and util.lexists(repo.wjoin(f)):
5042
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
   472
                repo.ui.debug(_("removing %s\n") % f)
f191bc3916f7 merge: do early copy to deal with issue636
Matt Mackall <mpm@selenic.com>
parents: 4997
diff changeset
   473
                os.unlink(repo.wjoin(f))
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   474
        elif m == "g": # get
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   475
            flags = a[2]
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   476
            repo.ui.note(_("getting %s\n") % f)
3303
488d3062d225 merge: eliminate nodes from action list
Matt Mackall <mpm@selenic.com>
parents: 3299
diff changeset
   477
            t = mctx.filectx(f).data()
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   478
            repo.wwrite(f, t, flags)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   479
            updated += 1
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   480
        elif m == "d": # directory rename
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   481
            f2, fd, flags = a[2:]
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   482
            if f:
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   483
                repo.ui.note(_("moving %s to %s\n") % (f, fd))
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   484
                t = wctx.filectx(f).data()
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   485
                repo.wwrite(fd, t, flags)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   486
                util.unlink(repo.wjoin(f))
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   487
            if f2:
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   488
                repo.ui.note(_("getting %s to %s\n") % (f2, fd))
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   489
                t = mctx.filectx(f2).data()
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   490
                repo.wwrite(fd, t, flags)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   491
            updated += 1
4674
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   492
        elif m == "dr": # divergent renames
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   493
            fl = a[2]
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   494
            repo.ui.warn("warning: detected divergent renames of %s to:\n" % f)
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   495
            for nf in fl:
723e0ddb6ada merge: warn user about divergent renames
Matt Mackall <mpm@selenic.com>
parents: 4635
diff changeset
   496
                repo.ui.warn(" %s\n" % nf)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   497
        elif m == "e": # exec
4007
20da40cc1c73 symlinks: minimal support for symlinks in merge/update
Matt Mackall <mpm@selenic.com>
parents: 4006
diff changeset
   498
            flags = a[2]
5704
5049bbf988e1 merge: use util.set_flags
Matt Mackall <mpm@selenic.com>
parents: 5700
diff changeset
   499
            util.set_flags(repo.wjoin(f), flags)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   500
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   501
    return updated, merged, removed, unresolved
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   502
3372
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
   503
def recordupdates(repo, action, branchmerge):
3315
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   504
    "record merge actions to the dirstate"
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   505
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   506
    for a in action:
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   507
        f, m = a[:2]
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   508
        if m == "r": # remove
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   509
            if branchmerge:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   510
                repo.dirstate.remove(f)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   511
            else:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   512
                repo.dirstate.forget(f)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   513
        elif m == "f": # forget
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   514
            repo.dirstate.forget(f)
4997
60c54154ec4c merge: don't forget to update the dirstate for exec bit changes
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   515
        elif m in "ge": # get or exec change
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   516
            if branchmerge:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   517
                repo.dirstate.normaldirty(f)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   518
            else:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   519
                repo.dirstate.normal(f)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   520
        elif m == "m": # merge
3303
488d3062d225 merge: eliminate nodes from action list
Matt Mackall <mpm@selenic.com>
parents: 3299
diff changeset
   521
            f2, fd, flag, move = a[2:]
3251
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
   522
            if branchmerge:
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
   523
                # We've done a branch merge, mark this file as merged
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
   524
                # so that we properly record the merger later
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   525
                repo.dirstate.merge(fd)
3372
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
   526
                if f != f2: # copy/rename
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
   527
                    if move:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   528
                        repo.dirstate.remove(f)
3372
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
   529
                    if f != fd:
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
   530
                        repo.dirstate.copy(f, fd)
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
   531
                    else:
ba7c74081861 merge: update dirstate correctly for non-branchmerge updates
Matt Mackall <mpm@selenic.com>
parents: 3371
diff changeset
   532
                        repo.dirstate.copy(f2, fd)
3251
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
   533
            else:
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
   534
                # We've update-merged a locally modified file, so
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
   535
                # we set the dirstate to emulate a normal checkout
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
   536
                # of that file some time in the past. Thus our
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
   537
                # merge will appear as a normal local file
c93ce7f10f85 merge: fixes for merge+rename
Matt Mackall <mpm@selenic.com>
parents: 3249
diff changeset
   538
                # modification.
5210
90d9ec0dc69d merge: forcefully mark files that we get from the second parent as dirty
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5161
diff changeset
   539
                repo.dirstate.normallookup(fd)
3308
ecc1bf27378c merge: unify merge and copy actions
Matt Mackall <mpm@selenic.com>
parents: 3307
diff changeset
   540
                if move:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   541
                    repo.dirstate.forget(f)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   542
        elif m == "d": # directory rename
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   543
            f2, fd, flag = a[2:]
4819
9797124581c9 merge: fix adding untracked files on directory rename (issue612)
Matt Mackall <mpm@selenic.com>
parents: 4748
diff changeset
   544
            if not f2 and f not in repo.dirstate:
9797124581c9 merge: fix adding untracked files on directory rename (issue612)
Matt Mackall <mpm@selenic.com>
parents: 4748
diff changeset
   545
                # untracked file moved
9797124581c9 merge: fix adding untracked files on directory rename (issue612)
Matt Mackall <mpm@selenic.com>
parents: 4748
diff changeset
   546
                continue
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   547
            if branchmerge:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   548
                repo.dirstate.add(fd)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   549
                if f:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   550
                    repo.dirstate.remove(f)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   551
                    repo.dirstate.copy(f, fd)
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   552
                if f2:
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   553
                    repo.dirstate.copy(f2, fd)
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   554
            else:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   555
                repo.dirstate.normal(fd)
3733
9e67fecbfd16 merge: handle directory renames
Matt Mackall <mpm@selenic.com>
parents: 3732
diff changeset
   556
                if f:
4904
6fd953d5faea dirstate: break update into separate functions
Matt Mackall <mpm@selenic.com>
parents: 4884
diff changeset
   557
                    repo.dirstate.forget(f)
3111
5cc62d99b785 merge: move apply and dirstate code into separate functions
Matt Mackall <mpm@selenic.com>
parents: 3110
diff changeset
   558
4917
126f527b3ba3 Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents: 4915
diff changeset
   559
def update(repo, node, branchmerge, force, partial):
3315
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   560
    """
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   561
    Perform a merge between the working directory and the given node
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   562
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   563
    branchmerge = whether to merge between branches
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   564
    force = whether to force branch merging or file overwriting
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   565
    partial = a function to filter file lists (dirstate not updated)
38be819a1225 merge: update some docstrings
Matt Mackall <mpm@selenic.com>
parents: 3314
diff changeset
   566
    """
2815
4870f795f681 Merge: combine force and forcemerge arguments
Matt Mackall <mpm@selenic.com>
parents: 2814
diff changeset
   567
4917
126f527b3ba3 Make repo locks recursive, eliminate all passing of lock/wlock
Matt Mackall <mpm@selenic.com>
parents: 4915
diff changeset
   568
    wlock = repo.wlock()
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   569
    try:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   570
        wc = repo.workingctx()
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   571
        if node is None:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   572
            # tip of current branch
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   573
            try:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   574
                node = repo.branchtags()[wc.branch()]
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   575
            except KeyError:
5570
78a6b985882f update: default to tipmost branch if default branch doesn't exist
Matt Mackall <mpm@selenic.com>
parents: 5489
diff changeset
   576
                if wc.branch() == "default": # no default branch!
78a6b985882f update: default to tipmost branch if default branch doesn't exist
Matt Mackall <mpm@selenic.com>
parents: 5489
diff changeset
   577
                    node = repo.lookup("tip") # update to tip
78a6b985882f update: default to tipmost branch if default branch doesn't exist
Matt Mackall <mpm@selenic.com>
parents: 5489
diff changeset
   578
                else:
78a6b985882f update: default to tipmost branch if default branch doesn't exist
Matt Mackall <mpm@selenic.com>
parents: 5489
diff changeset
   579
                    raise util.Abort(_("branch %s not found") % wc.branch())
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   580
        overwrite = force and not branchmerge
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   581
        forcemerge = force and branchmerge
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   582
        pl = wc.parents()
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   583
        p1, p2 = pl[0], repo.changectx(node)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   584
        pa = p1.ancestor(p2)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   585
        fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   586
        fastforward = False
3314
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
   587
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   588
        ### check phase
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   589
        if not overwrite and len(pl) > 1:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   590
            raise util.Abort(_("outstanding uncommitted merges"))
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   591
        if pa == p1 or pa == p2: # is there a linear path from p1 to p2?
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   592
            if branchmerge:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   593
                if p1.branch() != p2.branch() and pa != p2:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   594
                    fastforward = True
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   595
                else:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   596
                    raise util.Abort(_("there is nothing to merge, just use "
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   597
                                       "'hg update' or look at 'hg heads'"))
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   598
        elif not (overwrite or branchmerge):
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   599
            raise util.Abort(_("update spans branches, use 'hg merge' "
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   600
                               "or 'hg update -C' to lose changes"))
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   601
        if branchmerge and not forcemerge:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   602
            if wc.files():
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   603
                raise util.Abort(_("outstanding uncommitted changes"))
2814
0f787997e3c2 Merge: move most tests to the beginning
Matt Mackall <mpm@selenic.com>
parents: 2813
diff changeset
   604
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   605
        ### calculate phase
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   606
        action = []
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   607
        if not force:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   608
            checkunknown(wc, p2)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   609
        if not util.checkfolding(repo.path):
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   610
            checkcollision(p2)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   611
        if not branchmerge:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   612
            action += forgetremoved(wc, p2)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   613
        action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   614
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   615
        ### apply phase
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   616
        if not branchmerge: # just jump to the new rev
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   617
            fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   618
        if not partial:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   619
            repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
2775
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   620
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   621
        stats = applyupdates(repo, action, wc, p2)
2899
8743188f4d2e merge: consolidate dirstate updates
Matt Mackall <mpm@selenic.com>
parents: 2898
diff changeset
   622
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   623
        if not partial:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   624
            recordupdates(repo, action, branchmerge)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   625
            repo.dirstate.setparents(fp1, fp2)
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   626
            if not branchmerge and not fastforward:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   627
                repo.dirstate.setbranch(p2.branch())
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   628
            repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
3314
b16456909a0a merge: various tidying
Matt Mackall <mpm@selenic.com>
parents: 3312
diff changeset
   629
4915
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   630
        return stats
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   631
    finally:
97b734fb9c6f Use try/finally pattern to cleanup locks and transactions
Matt Mackall <mpm@selenic.com>
parents: 4904
diff changeset
   632
        del wlock