mercurial/merge.py
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
Tue, 19 Feb 2008 19:20:10 -0300
changeset 6144 08e0825b8106
parent 6003 7855b88ba838
child 6211 f89fd07fc51d
permissions -rw-r--r--
revlog.revision: avoid opening the datafile without need. If there's no inline data, revlog.revision opens the data file every time it's called. This is useful if we're going to call chunk many times, but, if we're going to call it only once, it's better to let chunk open the file - if we're lucky, all the data we're going to need is already cached and we won't need to even look at the file.
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
b550cd82f92a Move merge code to its own module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
from node import *
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