##// END OF EJS Templates
copies: skip directory rename checks when not merging...
Matt Mackall -
r6425:2d9328a2 default
parent child Browse files
Show More
@@ -1,194 +1,192 b''
1 # copies.py - copy detection for Mercurial
1 # copies.py - copy detection for Mercurial
2 #
2 #
3 # Copyright 2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2008 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from node import nullid, nullrev
8 from node import nullid, nullrev
9 from i18n import _
9 from i18n import _
10 import util, ancestor
10 import util, ancestor
11
11
12 def _nonoverlap(d1, d2, d3):
12 def _nonoverlap(d1, d2, d3):
13 "Return list of elements in d1 not in d2 or d3"
13 "Return list of elements in d1 not in d2 or d3"
14 l = [d for d in d1 if d not in d3 and d not in d2]
14 l = [d for d in d1 if d not in d3 and d not in d2]
15 l.sort()
15 l.sort()
16 return l
16 return l
17
17
18 def _dirname(f):
18 def _dirname(f):
19 s = f.rfind("/")
19 s = f.rfind("/")
20 if s == -1:
20 if s == -1:
21 return ""
21 return ""
22 return f[:s]
22 return f[:s]
23
23
24 def _dirs(files):
24 def _dirs(files):
25 d = {}
25 d = {}
26 for f in files:
26 for f in files:
27 f = _dirname(f)
27 f = _dirname(f)
28 while f not in d:
28 while f not in d:
29 d[f] = True
29 d[f] = True
30 f = _dirname(f)
30 f = _dirname(f)
31 return d
31 return d
32
32
33 def _findoldnames(fctx, limit):
33 def _findoldnames(fctx, limit):
34 "find files that path was copied from, back to linkrev limit"
34 "find files that path was copied from, back to linkrev limit"
35 old = {}
35 old = {}
36 seen = {}
36 seen = {}
37 orig = fctx.path()
37 orig = fctx.path()
38 visit = [(fctx, 0)]
38 visit = [(fctx, 0)]
39 while visit:
39 while visit:
40 fc, depth = visit.pop()
40 fc, depth = visit.pop()
41 s = str(fc)
41 s = str(fc)
42 if s in seen:
42 if s in seen:
43 continue
43 continue
44 seen[s] = 1
44 seen[s] = 1
45 if fc.path() != orig and fc.path() not in old:
45 if fc.path() != orig and fc.path() not in old:
46 old[fc.path()] = (depth, fc.path()) # remember depth
46 old[fc.path()] = (depth, fc.path()) # remember depth
47 if fc.rev() < limit and fc.rev() is not None:
47 if fc.rev() < limit and fc.rev() is not None:
48 continue
48 continue
49 visit += [(p, depth - 1) for p in fc.parents()]
49 visit += [(p, depth - 1) for p in fc.parents()]
50
50
51 # return old names sorted by depth
51 # return old names sorted by depth
52 old = old.values()
52 old = old.values()
53 old.sort()
53 old.sort()
54 return [o[1] for o in old]
54 return [o[1] for o in old]
55
55
56 def copies(repo, c1, c2, ca):
56 def copies(repo, c1, c2, ca, checkdirs=False):
57 """
57 """
58 Find moves and copies between context c1 and c2
58 Find moves and copies between context c1 and c2
59 """
59 """
60 # avoid silly behavior for update from empty dir
60 # avoid silly behavior for update from empty dir
61 if not c1 or not c2:
61 if not c1 or not c2:
62 return {}, {}
62 return {}, {}
63
63
64 rev1, rev2 = c1.rev(), c2.rev()
64 rev1, rev2 = c1.rev(), c2.rev()
65 if rev1 is None: # c1 is a workingctx
65 if rev1 is None: # c1 is a workingctx
66 rev1 = c1.parents()[0].rev()
66 rev1 = c1.parents()[0].rev()
67 if rev2 is None: # c2 is a workingctx
67 if rev2 is None: # c2 is a workingctx
68 rev2 = c2.parents()[0].rev()
68 rev2 = c2.parents()[0].rev()
69 pr = repo.changelog.parentrevs
69 pr = repo.changelog.parentrevs
70 def parents(rev):
70 def parents(rev):
71 return [p for p in pr(rev) if p != nullrev]
71 return [p for p in pr(rev) if p != nullrev]
72 limit = min(ancestor.symmetricdifference(rev1, rev2, parents))
72 limit = min(ancestor.symmetricdifference(rev1, rev2, parents))
73 m1 = c1.manifest()
73 m1 = c1.manifest()
74 m2 = c2.manifest()
74 m2 = c2.manifest()
75 ma = ca.manifest()
75 ma = ca.manifest()
76
76
77 def makectx(f, n):
77 def makectx(f, n):
78 if len(n) != 20: # in a working context?
78 if len(n) != 20: # in a working context?
79 if c1.rev() is None:
79 if c1.rev() is None:
80 return c1.filectx(f)
80 return c1.filectx(f)
81 return c2.filectx(f)
81 return c2.filectx(f)
82 return repo.filectx(f, fileid=n)
82 return repo.filectx(f, fileid=n)
83 ctx = util.cachefunc(makectx)
83 ctx = util.cachefunc(makectx)
84
84
85 copy = {}
85 copy = {}
86 fullcopy = {}
86 fullcopy = {}
87 diverge = {}
87 diverge = {}
88
88
89 def checkcopies(f, m1, m2):
89 def checkcopies(f, m1, m2):
90 '''check possible copies of f from m1 to m2'''
90 '''check possible copies of f from m1 to m2'''
91 c1 = ctx(f, m1[f])
91 c1 = ctx(f, m1[f])
92 for of in _findoldnames(c1, limit):
92 for of in _findoldnames(c1, limit):
93 fullcopy[f] = of # remember for dir rename detection
93 fullcopy[f] = of # remember for dir rename detection
94 if of in m2: # original file not in other manifest?
94 if of in m2: # original file not in other manifest?
95 # if the original file is unchanged on the other branch,
95 # if the original file is unchanged on the other branch,
96 # no merge needed
96 # no merge needed
97 if m2[of] != ma.get(of):
97 if m2[of] != ma.get(of):
98 c2 = ctx(of, m2[of])
98 c2 = ctx(of, m2[of])
99 ca = c1.ancestor(c2)
99 ca = c1.ancestor(c2)
100 # related and named changed on only one side?
100 # related and named changed on only one side?
101 if ca and (ca.path() == f or ca.path() == c2.path()):
101 if ca and (ca.path() == f or ca.path() == c2.path()):
102 if c1 != ca or c2 != ca: # merge needed?
102 if c1 != ca or c2 != ca: # merge needed?
103 copy[f] = of
103 copy[f] = of
104 elif of in ma:
104 elif of in ma:
105 diverge.setdefault(of, []).append(f)
105 diverge.setdefault(of, []).append(f)
106
106
107 if not repo.ui.configbool("merge", "followcopies", True):
108 return {}, {}
109
110 repo.ui.debug(_(" searching for copies back to rev %d\n") % limit)
107 repo.ui.debug(_(" searching for copies back to rev %d\n") % limit)
111
108
112 u1 = _nonoverlap(m1, m2, ma)
109 u1 = _nonoverlap(m1, m2, ma)
113 u2 = _nonoverlap(m2, m1, ma)
110 u2 = _nonoverlap(m2, m1, ma)
114
111
115 if u1:
112 if u1:
116 repo.ui.debug(_(" unmatched files in local:\n %s\n")
113 repo.ui.debug(_(" unmatched files in local:\n %s\n")
117 % "\n ".join(u1))
114 % "\n ".join(u1))
118 if u2:
115 if u2:
119 repo.ui.debug(_(" unmatched files in other:\n %s\n")
116 repo.ui.debug(_(" unmatched files in other:\n %s\n")
120 % "\n ".join(u2))
117 % "\n ".join(u2))
121
118
122 for f in u1:
119 for f in u1:
123 checkcopies(f, m1, m2)
120 checkcopies(f, m1, m2)
124 for f in u2:
121 for f in u2:
125 checkcopies(f, m2, m1)
122 checkcopies(f, m2, m1)
126
123
127 diverge2 = {}
124 diverge2 = {}
128 for of, fl in diverge.items():
125 for of, fl in diverge.items():
129 if len(fl) == 1:
126 if len(fl) == 1:
130 del diverge[of] # not actually divergent
127 del diverge[of] # not actually divergent
131 else:
128 else:
132 diverge2.update(dict.fromkeys(fl)) # reverse map for below
129 diverge2.update(dict.fromkeys(fl)) # reverse map for below
133
130
134 if fullcopy:
131 if fullcopy:
135 repo.ui.debug(_(" all copies found (* = to merge, ! = divergent):\n"))
132 repo.ui.debug(_(" all copies found (* = to merge, ! = divergent):\n"))
136 for f in fullcopy:
133 for f in fullcopy:
137 note = ""
134 note = ""
138 if f in copy: note += "*"
135 if f in copy: note += "*"
139 if f in diverge2: note += "!"
136 if f in diverge2: note += "!"
140 repo.ui.debug(_(" %s -> %s %s\n") % (f, fullcopy[f], note))
137 repo.ui.debug(_(" %s -> %s %s\n") % (f, fullcopy[f], note))
141 del diverge2
138 del diverge2
142
139
143 if not fullcopy or not repo.ui.configbool("merge", "followdirs", True):
140 if not fullcopy or not checkdirs:
144 return copy, diverge
141 return copy, diverge
145
142
146 repo.ui.debug(_(" checking for directory renames\n"))
143 repo.ui.debug(_(" checking for directory renames\n"))
147
144
148 # generate a directory move map
145 # generate a directory move map
149 d1, d2 = _dirs(m1), _dirs(m2)
146 d1, d2 = _dirs(m1), _dirs(m2)
150 invalid = {}
147 invalid = {}
151 dirmove = {}
148 dirmove = {}
152
149
153 # examine each file copy for a potential directory move, which is
150 # examine each file copy for a potential directory move, which is
154 # when all the files in a directory are moved to a new directory
151 # when all the files in a directory are moved to a new directory
155 for dst, src in fullcopy.items():
152 for dst, src in fullcopy.items():
156 dsrc, ddst = _dirname(src), _dirname(dst)
153 dsrc, ddst = _dirname(src), _dirname(dst)
157 if dsrc in invalid:
154 if dsrc in invalid:
158 # already seen to be uninteresting
155 # already seen to be uninteresting
159 continue
156 continue
160 elif dsrc in d1 and ddst in d1:
157 elif dsrc in d1 and ddst in d1:
161 # directory wasn't entirely moved locally
158 # directory wasn't entirely moved locally
162 invalid[dsrc] = True
159 invalid[dsrc] = True
163 elif dsrc in d2 and ddst in d2:
160 elif dsrc in d2 and ddst in d2:
164 # directory wasn't entirely moved remotely
161 # directory wasn't entirely moved remotely
165 invalid[dsrc] = True
162 invalid[dsrc] = True
166 elif dsrc in dirmove and dirmove[dsrc] != ddst:
163 elif dsrc in dirmove and dirmove[dsrc] != ddst:
167 # files from the same directory moved to two different places
164 # files from the same directory moved to two different places
168 invalid[dsrc] = True
165 invalid[dsrc] = True
169 else:
166 else:
170 # looks good so far
167 # looks good so far
171 dirmove[dsrc + "/"] = ddst + "/"
168 dirmove[dsrc + "/"] = ddst + "/"
172
169
173 for i in invalid:
170 for i in invalid:
174 if i in dirmove:
171 if i in dirmove:
175 del dirmove[i]
172 del dirmove[i]
176 del d1, d2, invalid
173 del d1, d2, invalid
177
174
178 if not dirmove:
175 if not dirmove:
179 return copy, diverge
176 return copy, diverge
180
177
181 for d in dirmove:
178 for d in dirmove:
182 repo.ui.debug(_(" dir %s -> %s\n") % (d, dirmove[d]))
179 repo.ui.debug(_(" dir %s -> %s\n") % (d, dirmove[d]))
183
180
184 # check unaccounted nonoverlapping files against directory moves
181 # check unaccounted nonoverlapping files against directory moves
185 for f in u1 + u2:
182 for f in u1 + u2:
186 if f not in fullcopy:
183 if f not in fullcopy:
187 for d in dirmove:
184 for d in dirmove:
188 if f.startswith(d):
185 if f.startswith(d):
189 # new file added in a directory that was moved, move it
186 # new file added in a directory that was moved, move it
190 copy[f] = dirmove[d] + f[len(d):]
187 df = dirmove[d] + f[len(d):]
188 copy[f] = df
191 repo.ui.debug(_(" file %s -> %s\n") % (f, copy[f]))
189 repo.ui.debug(_(" file %s -> %s\n") % (f, copy[f]))
192 break
190 break
193
191
194 return copy, diverge
192 return copy, diverge
@@ -1,411 +1,413 b''
1 # merge.py - directory-level update/merge handling for Mercurial
1 # merge.py - directory-level update/merge handling for Mercurial
2 #
2 #
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from node import nullid, nullrev
8 from node import nullid, nullrev
9 from i18n import _
9 from i18n import _
10 import errno, util, os, filemerge, copies
10 import errno, util, os, filemerge, copies
11
11
12 def _checkunknown(wctx, mctx):
12 def _checkunknown(wctx, mctx):
13 "check for collisions between unknown files and files in mctx"
13 "check for collisions between unknown files and files in mctx"
14 for f in wctx.unknown():
14 for f in wctx.unknown():
15 if f in mctx and mctx[f].cmp(wctx[f].data()):
15 if f in mctx and mctx[f].cmp(wctx[f].data()):
16 raise util.Abort(_("untracked file in working directory differs"
16 raise util.Abort(_("untracked file in working directory differs"
17 " from file in requested revision: '%s'") % f)
17 " from file in requested revision: '%s'") % f)
18
18
19 def _checkcollision(mctx):
19 def _checkcollision(mctx):
20 "check for case folding collisions in the destination context"
20 "check for case folding collisions in the destination context"
21 folded = {}
21 folded = {}
22 for fn in mctx:
22 for fn in mctx:
23 fold = fn.lower()
23 fold = fn.lower()
24 if fold in folded:
24 if fold in folded:
25 raise util.Abort(_("case-folding collision between %s and %s")
25 raise util.Abort(_("case-folding collision between %s and %s")
26 % (fn, folded[fold]))
26 % (fn, folded[fold]))
27 folded[fold] = fn
27 folded[fold] = fn
28
28
29 def _forgetremoved(wctx, mctx, branchmerge):
29 def _forgetremoved(wctx, mctx, branchmerge):
30 """
30 """
31 Forget removed files
31 Forget removed files
32
32
33 If we're jumping between revisions (as opposed to merging), and if
33 If we're jumping between revisions (as opposed to merging), and if
34 neither the working directory nor the target rev has the file,
34 neither the working directory nor the target rev has the file,
35 then we need to remove it from the dirstate, to prevent the
35 then we need to remove it from the dirstate, to prevent the
36 dirstate from listing the file when it is no longer in the
36 dirstate from listing the file when it is no longer in the
37 manifest.
37 manifest.
38
38
39 If we're merging, and the other revision has removed a file
39 If we're merging, and the other revision has removed a file
40 that is not present in the working directory, we need to mark it
40 that is not present in the working directory, we need to mark it
41 as removed.
41 as removed.
42 """
42 """
43
43
44 action = []
44 action = []
45 state = branchmerge and 'r' or 'f'
45 state = branchmerge and 'r' or 'f'
46 for f in wctx.deleted():
46 for f in wctx.deleted():
47 if f not in mctx:
47 if f not in mctx:
48 action.append((f, state))
48 action.append((f, state))
49
49
50 if not branchmerge:
50 if not branchmerge:
51 for f in wctx.removed():
51 for f in wctx.removed():
52 if f not in mctx:
52 if f not in mctx:
53 action.append((f, "f"))
53 action.append((f, "f"))
54
54
55 return action
55 return action
56
56
57 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
57 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
58 """
58 """
59 Merge p1 and p2 with ancestor ma and generate merge action list
59 Merge p1 and p2 with ancestor ma and generate merge action list
60
60
61 overwrite = whether we clobber working files
61 overwrite = whether we clobber working files
62 partial = function to filter file lists
62 partial = function to filter file lists
63 """
63 """
64
64
65 repo.ui.note(_("resolving manifests\n"))
65 repo.ui.note(_("resolving manifests\n"))
66 repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
66 repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial)))
67 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
67 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2))
68
68
69 m1 = p1.manifest()
69 m1 = p1.manifest()
70 m2 = p2.manifest()
70 m2 = p2.manifest()
71 ma = pa.manifest()
71 ma = pa.manifest()
72 backwards = (pa == p2)
72 backwards = (pa == p2)
73 action = []
73 action = []
74 copy, copied, diverge = {}, {}, {}
74 copy, copied, diverge = {}, {}, {}
75
75
76 def fmerge(f, f2=None, fa=None):
76 def fmerge(f, f2=None, fa=None):
77 """merge flags"""
77 """merge flags"""
78 if not f2:
78 if not f2:
79 f2 = f
79 f2 = f
80 fa = f
80 fa = f
81 a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
81 a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
82 if m == n: # flags agree
82 if m == n: # flags agree
83 return m # unchanged
83 return m # unchanged
84 if m and n: # flags are set but don't agree
84 if m and n: # flags are set but don't agree
85 if not a: # both differ from parent
85 if not a: # both differ from parent
86 r = repo.ui.prompt(
86 r = repo.ui.prompt(
87 _(" conflicting flags for %s\n"
87 _(" conflicting flags for %s\n"
88 "(n)one, e(x)ec or sym(l)ink?") % f, "[nxl]", "n")
88 "(n)one, e(x)ec or sym(l)ink?") % f, "[nxl]", "n")
89 return r != "n" and r or ''
89 return r != "n" and r or ''
90 if m == a:
90 if m == a:
91 return n # changed from m to n
91 return n # changed from m to n
92 return m # changed from n to m
92 return m # changed from n to m
93 if m and m != a: # changed from a to m
93 if m and m != a: # changed from a to m
94 return m
94 return m
95 if n and n != a: # changed from a to n
95 if n and n != a: # changed from a to n
96 return n
96 return n
97 return '' # flag was cleared
97 return '' # flag was cleared
98
98
99 def act(msg, m, f, *args):
99 def act(msg, m, f, *args):
100 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
100 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
101 action.append((f, m) + args)
101 action.append((f, m) + args)
102
102
103 if pa and not (backwards or overwrite):
103 if pa and not (backwards or overwrite):
104 copy, diverge = copies.copies(repo, p1, p2, pa)
104 if repo.ui.configbool("merge", "followcopies", True):
105 dirs = repo.ui.configbool("merge", "followdirs", True)
106 copy, diverge = copies.copies(repo, p1, p2, pa, dirs)
105 copied = dict.fromkeys(copy.values())
107 copied = dict.fromkeys(copy.values())
106 for of, fl in diverge.items():
108 for of, fl in diverge.items():
107 act("divergent renames", "dr", of, fl)
109 act("divergent renames", "dr", of, fl)
108
110
109 # Compare manifests
111 # Compare manifests
110 for f, n in m1.iteritems():
112 for f, n in m1.iteritems():
111 if partial and not partial(f):
113 if partial and not partial(f):
112 continue
114 continue
113 if f in m2:
115 if f in m2:
114 if overwrite or backwards:
116 if overwrite or backwards:
115 rflags = m2.flags(f)
117 rflags = m2.flags(f)
116 else:
118 else:
117 rflags = fmerge(f)
119 rflags = fmerge(f)
118 # are files different?
120 # are files different?
119 if n != m2[f]:
121 if n != m2[f]:
120 a = ma.get(f, nullid)
122 a = ma.get(f, nullid)
121 # are we clobbering?
123 # are we clobbering?
122 if overwrite:
124 if overwrite:
123 act("clobbering", "g", f, rflags)
125 act("clobbering", "g", f, rflags)
124 # or are we going back in time and clean?
126 # or are we going back in time and clean?
125 elif backwards and not n[20:]:
127 elif backwards and not n[20:]:
126 act("reverting", "g", f, rflags)
128 act("reverting", "g", f, rflags)
127 # are both different from the ancestor?
129 # are both different from the ancestor?
128 elif n != a and m2[f] != a:
130 elif n != a and m2[f] != a:
129 act("versions differ", "m", f, f, f, rflags, False)
131 act("versions differ", "m", f, f, f, rflags, False)
130 # is remote's version newer?
132 # is remote's version newer?
131 elif m2[f] != a:
133 elif m2[f] != a:
132 act("remote is newer", "g", f, rflags)
134 act("remote is newer", "g", f, rflags)
133 # local is newer, not overwrite, check mode bits
135 # local is newer, not overwrite, check mode bits
134 elif m1.flags(f) != rflags:
136 elif m1.flags(f) != rflags:
135 act("update permissions", "e", f, rflags)
137 act("update permissions", "e", f, rflags)
136 # contents same, check mode bits
138 # contents same, check mode bits
137 elif m1.flags(f) != rflags:
139 elif m1.flags(f) != rflags:
138 act("update permissions", "e", f, rflags)
140 act("update permissions", "e", f, rflags)
139 elif f in copied:
141 elif f in copied:
140 continue
142 continue
141 elif f in copy:
143 elif f in copy:
142 f2 = copy[f]
144 f2 = copy[f]
143 if f2 not in m2: # directory rename
145 if f2 not in m2: # directory rename
144 act("remote renamed directory to " + f2, "d",
146 act("remote renamed directory to " + f2, "d",
145 f, None, f2, m1.flags(f))
147 f, None, f2, m1.flags(f))
146 elif f2 in m1: # case 2 A,B/B/B
148 elif f2 in m1: # case 2 A,B/B/B
147 act("local copied to " + f2, "m",
149 act("local copied to " + f2, "m",
148 f, f2, f, fmerge(f, f2, f2), False)
150 f, f2, f, fmerge(f, f2, f2), False)
149 else: # case 4,21 A/B/B
151 else: # case 4,21 A/B/B
150 act("local moved to " + f2, "m",
152 act("local moved to " + f2, "m",
151 f, f2, f, fmerge(f, f2, f2), False)
153 f, f2, f, fmerge(f, f2, f2), False)
152 elif f in ma:
154 elif f in ma:
153 if n != ma[f] and not overwrite:
155 if n != ma[f] and not overwrite:
154 if repo.ui.prompt(
156 if repo.ui.prompt(
155 _(" local changed %s which remote deleted\n"
157 _(" local changed %s which remote deleted\n"
156 "use (c)hanged version or (d)elete?") % f,
158 "use (c)hanged version or (d)elete?") % f,
157 _("[cd]"), _("c")) == _("d"):
159 _("[cd]"), _("c")) == _("d"):
158 act("prompt delete", "r", f)
160 act("prompt delete", "r", f)
159 else:
161 else:
160 act("other deleted", "r", f)
162 act("other deleted", "r", f)
161 else:
163 else:
162 # file is created on branch or in working directory
164 # file is created on branch or in working directory
163 if (overwrite and n[20:] != "u") or (backwards and not n[20:]):
165 if (overwrite and n[20:] != "u") or (backwards and not n[20:]):
164 act("remote deleted", "r", f)
166 act("remote deleted", "r", f)
165
167
166 for f, n in m2.iteritems():
168 for f, n in m2.iteritems():
167 if partial and not partial(f):
169 if partial and not partial(f):
168 continue
170 continue
169 if f in m1:
171 if f in m1:
170 continue
172 continue
171 if f in copied:
173 if f in copied:
172 continue
174 continue
173 if f in copy:
175 if f in copy:
174 f2 = copy[f]
176 f2 = copy[f]
175 if f2 not in m1: # directory rename
177 if f2 not in m1: # directory rename
176 act("local renamed directory to " + f2, "d",
178 act("local renamed directory to " + f2, "d",
177 None, f, f2, m2.flags(f))
179 None, f, f2, m2.flags(f))
178 elif f2 in m2: # rename case 1, A/A,B/A
180 elif f2 in m2: # rename case 1, A/A,B/A
179 act("remote copied to " + f, "m",
181 act("remote copied to " + f, "m",
180 f2, f, f, fmerge(f2, f, f2), False)
182 f2, f, f, fmerge(f2, f, f2), False)
181 else: # case 3,20 A/B/A
183 else: # case 3,20 A/B/A
182 act("remote moved to " + f, "m",
184 act("remote moved to " + f, "m",
183 f2, f, f, fmerge(f2, f, f2), True)
185 f2, f, f, fmerge(f2, f, f2), True)
184 elif f in ma:
186 elif f in ma:
185 if overwrite or backwards:
187 if overwrite or backwards:
186 act("recreating", "g", f, m2.flags(f))
188 act("recreating", "g", f, m2.flags(f))
187 elif n != ma[f]:
189 elif n != ma[f]:
188 if repo.ui.prompt(
190 if repo.ui.prompt(
189 _("remote changed %s which local deleted\n"
191 _("remote changed %s which local deleted\n"
190 "use (c)hanged version or leave (d)eleted?") % f,
192 "use (c)hanged version or leave (d)eleted?") % f,
191 _("[cd]"), _("c")) == _("c"):
193 _("[cd]"), _("c")) == _("c"):
192 act("prompt recreating", "g", f, m2.flags(f))
194 act("prompt recreating", "g", f, m2.flags(f))
193 else:
195 else:
194 act("remote created", "g", f, m2.flags(f))
196 act("remote created", "g", f, m2.flags(f))
195
197
196 return action
198 return action
197
199
198 def applyupdates(repo, action, wctx, mctx):
200 def applyupdates(repo, action, wctx, mctx):
199 "apply the merge action list to the working directory"
201 "apply the merge action list to the working directory"
200
202
201 updated, merged, removed, unresolved = 0, 0, 0, 0
203 updated, merged, removed, unresolved = 0, 0, 0, 0
202 action.sort()
204 action.sort()
203 # prescan for copy/renames
205 # prescan for copy/renames
204 for a in action:
206 for a in action:
205 f, m = a[:2]
207 f, m = a[:2]
206 if m == 'm': # merge
208 if m == 'm': # merge
207 f2, fd, flags, move = a[2:]
209 f2, fd, flags, move = a[2:]
208 if f != fd:
210 if f != fd:
209 repo.ui.debug(_("copying %s to %s\n") % (f, fd))
211 repo.ui.debug(_("copying %s to %s\n") % (f, fd))
210 repo.wwrite(fd, repo.wread(f), flags)
212 repo.wwrite(fd, repo.wread(f), flags)
211
213
212 audit_path = util.path_auditor(repo.root)
214 audit_path = util.path_auditor(repo.root)
213
215
214 for a in action:
216 for a in action:
215 f, m = a[:2]
217 f, m = a[:2]
216 if f and f[0] == "/":
218 if f and f[0] == "/":
217 continue
219 continue
218 if m == "r": # remove
220 if m == "r": # remove
219 repo.ui.note(_("removing %s\n") % f)
221 repo.ui.note(_("removing %s\n") % f)
220 audit_path(f)
222 audit_path(f)
221 try:
223 try:
222 util.unlink(repo.wjoin(f))
224 util.unlink(repo.wjoin(f))
223 except OSError, inst:
225 except OSError, inst:
224 if inst.errno != errno.ENOENT:
226 if inst.errno != errno.ENOENT:
225 repo.ui.warn(_("update failed to remove %s: %s!\n") %
227 repo.ui.warn(_("update failed to remove %s: %s!\n") %
226 (f, inst.strerror))
228 (f, inst.strerror))
227 removed += 1
229 removed += 1
228 elif m == "m": # merge
230 elif m == "m": # merge
229 f2, fd, flags, move = a[2:]
231 f2, fd, flags, move = a[2:]
230 r = filemerge.filemerge(repo, f, fd, f2, wctx, mctx)
232 r = filemerge.filemerge(repo, f, fd, f2, wctx, mctx)
231 if r > 0:
233 if r > 0:
232 unresolved += 1
234 unresolved += 1
233 else:
235 else:
234 if r is None:
236 if r is None:
235 updated += 1
237 updated += 1
236 else:
238 else:
237 merged += 1
239 merged += 1
238 util.set_flags(repo.wjoin(fd), flags)
240 util.set_flags(repo.wjoin(fd), flags)
239 if f != fd and move and util.lexists(repo.wjoin(f)):
241 if f != fd and move and util.lexists(repo.wjoin(f)):
240 repo.ui.debug(_("removing %s\n") % f)
242 repo.ui.debug(_("removing %s\n") % f)
241 os.unlink(repo.wjoin(f))
243 os.unlink(repo.wjoin(f))
242 elif m == "g": # get
244 elif m == "g": # get
243 flags = a[2]
245 flags = a[2]
244 repo.ui.note(_("getting %s\n") % f)
246 repo.ui.note(_("getting %s\n") % f)
245 t = mctx.filectx(f).data()
247 t = mctx.filectx(f).data()
246 repo.wwrite(f, t, flags)
248 repo.wwrite(f, t, flags)
247 updated += 1
249 updated += 1
248 elif m == "d": # directory rename
250 elif m == "d": # directory rename
249 f2, fd, flags = a[2:]
251 f2, fd, flags = a[2:]
250 if f:
252 if f:
251 repo.ui.note(_("moving %s to %s\n") % (f, fd))
253 repo.ui.note(_("moving %s to %s\n") % (f, fd))
252 t = wctx.filectx(f).data()
254 t = wctx.filectx(f).data()
253 repo.wwrite(fd, t, flags)
255 repo.wwrite(fd, t, flags)
254 util.unlink(repo.wjoin(f))
256 util.unlink(repo.wjoin(f))
255 if f2:
257 if f2:
256 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
258 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
257 t = mctx.filectx(f2).data()
259 t = mctx.filectx(f2).data()
258 repo.wwrite(fd, t, flags)
260 repo.wwrite(fd, t, flags)
259 updated += 1
261 updated += 1
260 elif m == "dr": # divergent renames
262 elif m == "dr": # divergent renames
261 fl = a[2]
263 fl = a[2]
262 repo.ui.warn("warning: detected divergent renames of %s to:\n" % f)
264 repo.ui.warn("warning: detected divergent renames of %s to:\n" % f)
263 for nf in fl:
265 for nf in fl:
264 repo.ui.warn(" %s\n" % nf)
266 repo.ui.warn(" %s\n" % nf)
265 elif m == "e": # exec
267 elif m == "e": # exec
266 flags = a[2]
268 flags = a[2]
267 util.set_flags(repo.wjoin(f), flags)
269 util.set_flags(repo.wjoin(f), flags)
268
270
269 return updated, merged, removed, unresolved
271 return updated, merged, removed, unresolved
270
272
271 def recordupdates(repo, action, branchmerge):
273 def recordupdates(repo, action, branchmerge):
272 "record merge actions to the dirstate"
274 "record merge actions to the dirstate"
273
275
274 for a in action:
276 for a in action:
275 f, m = a[:2]
277 f, m = a[:2]
276 if m == "r": # remove
278 if m == "r": # remove
277 if branchmerge:
279 if branchmerge:
278 repo.dirstate.remove(f)
280 repo.dirstate.remove(f)
279 else:
281 else:
280 repo.dirstate.forget(f)
282 repo.dirstate.forget(f)
281 elif m == "f": # forget
283 elif m == "f": # forget
282 repo.dirstate.forget(f)
284 repo.dirstate.forget(f)
283 elif m in "ge": # get or exec change
285 elif m in "ge": # get or exec change
284 if branchmerge:
286 if branchmerge:
285 repo.dirstate.normaldirty(f)
287 repo.dirstate.normaldirty(f)
286 else:
288 else:
287 repo.dirstate.normal(f)
289 repo.dirstate.normal(f)
288 elif m == "m": # merge
290 elif m == "m": # merge
289 f2, fd, flag, move = a[2:]
291 f2, fd, flag, move = a[2:]
290 if branchmerge:
292 if branchmerge:
291 # We've done a branch merge, mark this file as merged
293 # We've done a branch merge, mark this file as merged
292 # so that we properly record the merger later
294 # so that we properly record the merger later
293 repo.dirstate.merge(fd)
295 repo.dirstate.merge(fd)
294 if f != f2: # copy/rename
296 if f != f2: # copy/rename
295 if move:
297 if move:
296 repo.dirstate.remove(f)
298 repo.dirstate.remove(f)
297 if f != fd:
299 if f != fd:
298 repo.dirstate.copy(f, fd)
300 repo.dirstate.copy(f, fd)
299 else:
301 else:
300 repo.dirstate.copy(f2, fd)
302 repo.dirstate.copy(f2, fd)
301 else:
303 else:
302 # We've update-merged a locally modified file, so
304 # We've update-merged a locally modified file, so
303 # we set the dirstate to emulate a normal checkout
305 # we set the dirstate to emulate a normal checkout
304 # of that file some time in the past. Thus our
306 # of that file some time in the past. Thus our
305 # merge will appear as a normal local file
307 # merge will appear as a normal local file
306 # modification.
308 # modification.
307 repo.dirstate.normallookup(fd)
309 repo.dirstate.normallookup(fd)
308 if move:
310 if move:
309 repo.dirstate.forget(f)
311 repo.dirstate.forget(f)
310 elif m == "d": # directory rename
312 elif m == "d": # directory rename
311 f2, fd, flag = a[2:]
313 f2, fd, flag = a[2:]
312 if not f2 and f not in repo.dirstate:
314 if not f2 and f not in repo.dirstate:
313 # untracked file moved
315 # untracked file moved
314 continue
316 continue
315 if branchmerge:
317 if branchmerge:
316 repo.dirstate.add(fd)
318 repo.dirstate.add(fd)
317 if f:
319 if f:
318 repo.dirstate.remove(f)
320 repo.dirstate.remove(f)
319 repo.dirstate.copy(f, fd)
321 repo.dirstate.copy(f, fd)
320 if f2:
322 if f2:
321 repo.dirstate.copy(f2, fd)
323 repo.dirstate.copy(f2, fd)
322 else:
324 else:
323 repo.dirstate.normal(fd)
325 repo.dirstate.normal(fd)
324 if f:
326 if f:
325 repo.dirstate.forget(f)
327 repo.dirstate.forget(f)
326
328
327 def update(repo, node, branchmerge, force, partial):
329 def update(repo, node, branchmerge, force, partial):
328 """
330 """
329 Perform a merge between the working directory and the given node
331 Perform a merge between the working directory and the given node
330
332
331 branchmerge = whether to merge between branches
333 branchmerge = whether to merge between branches
332 force = whether to force branch merging or file overwriting
334 force = whether to force branch merging or file overwriting
333 partial = a function to filter file lists (dirstate not updated)
335 partial = a function to filter file lists (dirstate not updated)
334 """
336 """
335
337
336 wlock = repo.wlock()
338 wlock = repo.wlock()
337 try:
339 try:
338 wc = repo.workingctx()
340 wc = repo.workingctx()
339 if node is None:
341 if node is None:
340 # tip of current branch
342 # tip of current branch
341 try:
343 try:
342 node = repo.branchtags()[wc.branch()]
344 node = repo.branchtags()[wc.branch()]
343 except KeyError:
345 except KeyError:
344 if wc.branch() == "default": # no default branch!
346 if wc.branch() == "default": # no default branch!
345 node = repo.lookup("tip") # update to tip
347 node = repo.lookup("tip") # update to tip
346 else:
348 else:
347 raise util.Abort(_("branch %s not found") % wc.branch())
349 raise util.Abort(_("branch %s not found") % wc.branch())
348 overwrite = force and not branchmerge
350 overwrite = force and not branchmerge
349 pl = wc.parents()
351 pl = wc.parents()
350 p1, p2 = pl[0], repo.changectx(node)
352 p1, p2 = pl[0], repo.changectx(node)
351 pa = p1.ancestor(p2)
353 pa = p1.ancestor(p2)
352 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
354 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
353 fastforward = False
355 fastforward = False
354
356
355 ### check phase
357 ### check phase
356 if not overwrite and len(pl) > 1:
358 if not overwrite and len(pl) > 1:
357 raise util.Abort(_("outstanding uncommitted merges"))
359 raise util.Abort(_("outstanding uncommitted merges"))
358 if branchmerge:
360 if branchmerge:
359 if pa == p2:
361 if pa == p2:
360 raise util.Abort(_("can't merge with ancestor"))
362 raise util.Abort(_("can't merge with ancestor"))
361 elif pa == p1:
363 elif pa == p1:
362 if p1.branch() != p2.branch():
364 if p1.branch() != p2.branch():
363 fastforward = True
365 fastforward = True
364 else:
366 else:
365 raise util.Abort(_("nothing to merge (use 'hg update'"
367 raise util.Abort(_("nothing to merge (use 'hg update'"
366 " or check 'hg heads')"))
368 " or check 'hg heads')"))
367 if not force and (wc.files() or wc.deleted()):
369 if not force and (wc.files() or wc.deleted()):
368 raise util.Abort(_("outstanding uncommitted changes"))
370 raise util.Abort(_("outstanding uncommitted changes"))
369 elif not overwrite:
371 elif not overwrite:
370 if pa == p1 or pa == p2: # linear
372 if pa == p1 or pa == p2: # linear
371 pass # all good
373 pass # all good
372 elif p1.branch() == p2.branch():
374 elif p1.branch() == p2.branch():
373 if wc.files() or wc.deleted():
375 if wc.files() or wc.deleted():
374 raise util.Abort(_("crosses branches (use 'hg merge' or "
376 raise util.Abort(_("crosses branches (use 'hg merge' or "
375 "'hg update -C' to discard changes)"))
377 "'hg update -C' to discard changes)"))
376 raise util.Abort(_("crosses branches (use 'hg merge' "
378 raise util.Abort(_("crosses branches (use 'hg merge' "
377 "or 'hg update -C')"))
379 "or 'hg update -C')"))
378 elif wc.files() or wc.deleted():
380 elif wc.files() or wc.deleted():
379 raise util.Abort(_("crosses named branches (use "
381 raise util.Abort(_("crosses named branches (use "
380 "'hg update -C' to discard changes)"))
382 "'hg update -C' to discard changes)"))
381 else:
383 else:
382 # Allow jumping branches if there are no changes
384 # Allow jumping branches if there are no changes
383 overwrite = True
385 overwrite = True
384
386
385 ### calculate phase
387 ### calculate phase
386 action = []
388 action = []
387 if not force:
389 if not force:
388 _checkunknown(wc, p2)
390 _checkunknown(wc, p2)
389 if not util.checkfolding(repo.path):
391 if not util.checkfolding(repo.path):
390 _checkcollision(p2)
392 _checkcollision(p2)
391 action += _forgetremoved(wc, p2, branchmerge)
393 action += _forgetremoved(wc, p2, branchmerge)
392 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
394 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
393
395
394 ### apply phase
396 ### apply phase
395 if not branchmerge: # just jump to the new rev
397 if not branchmerge: # just jump to the new rev
396 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
398 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
397 if not partial:
399 if not partial:
398 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
400 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
399
401
400 stats = applyupdates(repo, action, wc, p2)
402 stats = applyupdates(repo, action, wc, p2)
401
403
402 if not partial:
404 if not partial:
403 recordupdates(repo, action, branchmerge)
405 recordupdates(repo, action, branchmerge)
404 repo.dirstate.setparents(fp1, fp2)
406 repo.dirstate.setparents(fp1, fp2)
405 if not branchmerge and not fastforward:
407 if not branchmerge and not fastforward:
406 repo.dirstate.setbranch(p2.branch())
408 repo.dirstate.setbranch(p2.branch())
407 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
409 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
408
410
409 return stats
411 return stats
410 finally:
412 finally:
411 del wlock
413 del wlock
@@ -1,68 +1,76 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 add()
3 add()
4 {
4 {
5 echo $2 >> $1
5 echo $2 >> $1
6 }
6 }
7
7
8 hg init t
8 hg init t
9 cd t
9 cd t
10
10
11 # set up a boring main branch
11 # set up a boring main branch
12 add a a
12 add a a
13 hg add a
13 hg add a
14 mkdir x
15 add x/x x
16 hg add x/x
14 hg ci -m0
17 hg ci -m0
15
18
16 add a m1
19 add a m1
17 hg ci -m1
20 hg ci -m1
18
21
19 add a m2
22 add a m2
23 add x/y y1
24 hg add x/y
20 hg ci -m2
25 hg ci -m2
21
26
22 show()
27 show()
23 {
28 {
24 echo "- $2: $1"
29 echo "- $2: $1"
25 hg st -C $1
30 hg st -C $1
26 echo
31 echo
27 hg diff --git $1
32 hg diff --git $1
28 echo
33 echo
29 }
34 }
30
35
31 count=0
36 count=0
32 # make a new branch and get diff/status output
37 # make a new branch and get diff/status output
33 # $1 - first commit
38 # $1 - first commit
34 # $2 - second commit
39 # $2 - second commit
35 # $3 - working dir action
40 # $3 - working dir action
36 # $4 - test description
41 # $4 - test description
37 tb()
42 tb()
38 {
43 {
39 hg co -q -C 0
44 hg co -q -C 0
40
45
41 add a $count
46 add a $count
42 count=`expr $count + 1`
47 count=`expr $count + 1`
43 hg ci -m "t0"
48 hg ci -m "t0"
44 $1
49 $1
45 hg ci -m "t1"
50 hg ci -m "t1"
46 $2
51 $2
47 hg ci -m "t2"
52 hg ci -m "t2"
48 $3
53 $3
49
54
50 echo "** $4 **"
55 echo "** $4 **"
51 echo "** $1 / $2 / $3"
56 echo "** $1 / $2 / $3"
52 show "" "working to parent"
57 show "" "working to parent"
53 show "--rev 0" "working to root"
58 show "--rev 0" "working to root"
54 show "--rev 2" "working to branch"
59 show "--rev 2" "working to branch"
55 show "--rev 0 --rev ." "root to parent"
60 show "--rev 0 --rev ." "root to parent"
56 show "--rev . --rev 0" "parent to root"
61 show "--rev . --rev 0" "parent to root"
57 show "--rev 2 --rev ." "branch to parent"
62 show "--rev 2 --rev ." "branch to parent"
58 show "--rev . --rev 2" "parent to branch"
63 show "--rev . --rev 2" "parent to branch"
59 echo
64 echo
60 }
65 }
61
66
67
62 tb "add a a1" "add a a2" "hg mv a b" "rename in working dir"
68 tb "add a a1" "add a a2" "hg mv a b" "rename in working dir"
63 tb "add a a1" "add a a2" "hg cp a b" "copy in working dir"
69 tb "add a a1" "add a a2" "hg cp a b" "copy in working dir"
64 tb "hg mv a b" "add b b1" "add b w" "single rename"
70 tb "hg mv a b" "add b b1" "add b w" "single rename"
65 tb "hg cp a b" "add b b1" "add a w" "single copy"
71 tb "hg cp a b" "add b b1" "add a w" "single copy"
66 tb "hg mv a b" "hg mv b c" "hg mv c d" "rename chain"
72 tb "hg mv a b" "hg mv b c" "hg mv c d" "rename chain"
67 tb "hg cp a b" "hg cp b c" "hg cp c d" "copy chain"
73 tb "hg cp a b" "hg cp b c" "hg cp c d" "copy chain"
68 tb "add a a1" "hg mv a b" "hg mv b a" "circular rename"
74 tb "add a a1" "hg mv a b" "hg mv b a" "circular rename"
75
76 tb "hg mv x y" "add y/x x1" "add y/x x2" "directory move"
@@ -1,902 +1,1220 b''
1 created new head
1 created new head
2 ** rename in working dir **
2 ** rename in working dir **
3 ** add a a1 / add a a2 / hg mv a b
3 ** add a a1 / add a a2 / hg mv a b
4 - working to parent:
4 - working to parent:
5 A b
5 A b
6 a
6 a
7 R a
7 R a
8
8
9 diff --git a/a b/b
9 diff --git a/a b/b
10 rename from a
10 rename from a
11 rename to b
11 rename to b
12
12
13 - working to root: --rev 0
13 - working to root: --rev 0
14 A b
14 A b
15 a
15 a
16 R a
16 R a
17
17
18 diff --git a/a b/b
18 diff --git a/a b/b
19 rename from a
19 rename from a
20 rename to b
20 rename to b
21 --- a/a
21 --- a/a
22 +++ b/b
22 +++ b/b
23 @@ -1,1 +1,4 @@
23 @@ -1,1 +1,4 @@
24 a
24 a
25 +0
25 +0
26 +a1
26 +a1
27 +a2
27 +a2
28
28
29 - working to branch: --rev 2
29 - working to branch: --rev 2
30 A b
30 A b
31 a
31 a
32 R a
32 R a
33 R x/y
33
34
34 diff --git a/a b/b
35 diff --git a/a b/b
35 rename from a
36 rename from a
36 rename to b
37 rename to b
37 --- a/a
38 --- a/a
38 +++ b/b
39 +++ b/b
39 @@ -1,3 +1,4 @@
40 @@ -1,3 +1,4 @@
40 a
41 a
41 -m1
42 -m1
42 -m2
43 -m2
43 +0
44 +0
44 +a1
45 +a1
45 +a2
46 +a2
47 diff --git a/x/y b/x/y
48 deleted file mode 100644
49 --- a/x/y
50 +++ /dev/null
51 @@ -1,1 +0,0 @@
52 -y1
46
53
47 - root to parent: --rev 0 --rev .
54 - root to parent: --rev 0 --rev .
48 M a
55 M a
49
56
50 diff --git a/a b/a
57 diff --git a/a b/a
51 --- a/a
58 --- a/a
52 +++ b/a
59 +++ b/a
53 @@ -1,1 +1,4 @@
60 @@ -1,1 +1,4 @@
54 a
61 a
55 +0
62 +0
56 +a1
63 +a1
57 +a2
64 +a2
58
65
59 - parent to root: --rev . --rev 0
66 - parent to root: --rev . --rev 0
60 M a
67 M a
61
68
62 diff --git a/a b/a
69 diff --git a/a b/a
63 --- a/a
70 --- a/a
64 +++ b/a
71 +++ b/a
65 @@ -1,4 +1,1 @@
72 @@ -1,4 +1,1 @@
66 a
73 a
67 -0
74 -0
68 -a1
75 -a1
69 -a2
76 -a2
70
77
71 - branch to parent: --rev 2 --rev .
78 - branch to parent: --rev 2 --rev .
72 M a
79 M a
80 R x/y
73
81
74 diff --git a/a b/a
82 diff --git a/a b/a
75 --- a/a
83 --- a/a
76 +++ b/a
84 +++ b/a
77 @@ -1,3 +1,4 @@
85 @@ -1,3 +1,4 @@
78 a
86 a
79 -m1
87 -m1
80 -m2
88 -m2
81 +0
89 +0
82 +a1
90 +a1
83 +a2
91 +a2
92 diff --git a/x/y b/x/y
93 deleted file mode 100644
94 --- a/x/y
95 +++ /dev/null
96 @@ -1,1 +0,0 @@
97 -y1
84
98
85 - parent to branch: --rev . --rev 2
99 - parent to branch: --rev . --rev 2
86 M a
100 M a
101 A x/y
87
102
88 diff --git a/a b/a
103 diff --git a/a b/a
89 --- a/a
104 --- a/a
90 +++ b/a
105 +++ b/a
91 @@ -1,4 +1,3 @@
106 @@ -1,4 +1,3 @@
92 a
107 a
93 -0
108 -0
94 -a1
109 -a1
95 -a2
110 -a2
96 +m1
111 +m1
97 +m2
112 +m2
113 diff --git a/x/y b/x/y
114 new file mode 100644
115 --- /dev/null
116 +++ b/x/y
117 @@ -0,0 +1,1 @@
118 +y1
98
119
99
120
100 created new head
121 created new head
101 ** copy in working dir **
122 ** copy in working dir **
102 ** add a a1 / add a a2 / hg cp a b
123 ** add a a1 / add a a2 / hg cp a b
103 - working to parent:
124 - working to parent:
104 A b
125 A b
105 a
126 a
106
127
107 diff --git a/a b/b
128 diff --git a/a b/b
108 copy from a
129 copy from a
109 copy to b
130 copy to b
110
131
111 - working to root: --rev 0
132 - working to root: --rev 0
112 M a
133 M a
113 A b
134 A b
114 a
135 a
115
136
116 diff --git a/a b/a
137 diff --git a/a b/a
117 --- a/a
138 --- a/a
118 +++ b/a
139 +++ b/a
119 @@ -1,1 +1,4 @@
140 @@ -1,1 +1,4 @@
120 a
141 a
121 +1
142 +1
122 +a1
143 +a1
123 +a2
144 +a2
124 diff --git a/a b/b
145 diff --git a/a b/b
125 copy from a
146 copy from a
126 copy to b
147 copy to b
127 --- a/a
148 --- a/a
128 +++ b/b
149 +++ b/b
129 @@ -1,1 +1,4 @@
150 @@ -1,1 +1,4 @@
130 a
151 a
131 +1
152 +1
132 +a1
153 +a1
133 +a2
154 +a2
134
155
135 - working to branch: --rev 2
156 - working to branch: --rev 2
136 M a
157 M a
137 A b
158 A b
138 a
159 a
160 R x/y
139
161
140 diff --git a/a b/a
162 diff --git a/a b/a
141 --- a/a
163 --- a/a
142 +++ b/a
164 +++ b/a
143 @@ -1,3 +1,4 @@
165 @@ -1,3 +1,4 @@
144 a
166 a
145 -m1
167 -m1
146 -m2
168 -m2
147 +1
169 +1
148 +a1
170 +a1
149 +a2
171 +a2
150 diff --git a/a b/b
172 diff --git a/a b/b
151 copy from a
173 copy from a
152 copy to b
174 copy to b
153 --- a/a
175 --- a/a
154 +++ b/b
176 +++ b/b
155 @@ -1,3 +1,4 @@
177 @@ -1,3 +1,4 @@
156 a
178 a
157 -m1
179 -m1
158 -m2
180 -m2
159 +1
181 +1
160 +a1
182 +a1
161 +a2
183 +a2
184 diff --git a/x/y b/x/y
185 deleted file mode 100644
186 --- a/x/y
187 +++ /dev/null
188 @@ -1,1 +0,0 @@
189 -y1
162
190
163 - root to parent: --rev 0 --rev .
191 - root to parent: --rev 0 --rev .
164 M a
192 M a
165
193
166 diff --git a/a b/a
194 diff --git a/a b/a
167 --- a/a
195 --- a/a
168 +++ b/a
196 +++ b/a
169 @@ -1,1 +1,4 @@
197 @@ -1,1 +1,4 @@
170 a
198 a
171 +1
199 +1
172 +a1
200 +a1
173 +a2
201 +a2
174
202
175 - parent to root: --rev . --rev 0
203 - parent to root: --rev . --rev 0
176 M a
204 M a
177
205
178 diff --git a/a b/a
206 diff --git a/a b/a
179 --- a/a
207 --- a/a
180 +++ b/a
208 +++ b/a
181 @@ -1,4 +1,1 @@
209 @@ -1,4 +1,1 @@
182 a
210 a
183 -1
211 -1
184 -a1
212 -a1
185 -a2
213 -a2
186
214
187 - branch to parent: --rev 2 --rev .
215 - branch to parent: --rev 2 --rev .
188 M a
216 M a
217 R x/y
189
218
190 diff --git a/a b/a
219 diff --git a/a b/a
191 --- a/a
220 --- a/a
192 +++ b/a
221 +++ b/a
193 @@ -1,3 +1,4 @@
222 @@ -1,3 +1,4 @@
194 a
223 a
195 -m1
224 -m1
196 -m2
225 -m2
197 +1
226 +1
198 +a1
227 +a1
199 +a2
228 +a2
229 diff --git a/x/y b/x/y
230 deleted file mode 100644
231 --- a/x/y
232 +++ /dev/null
233 @@ -1,1 +0,0 @@
234 -y1
200
235
201 - parent to branch: --rev . --rev 2
236 - parent to branch: --rev . --rev 2
202 M a
237 M a
238 A x/y
203
239
204 diff --git a/a b/a
240 diff --git a/a b/a
205 --- a/a
241 --- a/a
206 +++ b/a
242 +++ b/a
207 @@ -1,4 +1,3 @@
243 @@ -1,4 +1,3 @@
208 a
244 a
209 -1
245 -1
210 -a1
246 -a1
211 -a2
247 -a2
212 +m1
248 +m1
213 +m2
249 +m2
250 diff --git a/x/y b/x/y
251 new file mode 100644
252 --- /dev/null
253 +++ b/x/y
254 @@ -0,0 +1,1 @@
255 +y1
214
256
215
257
216 created new head
258 created new head
217 ** single rename **
259 ** single rename **
218 ** hg mv a b / add b b1 / add b w
260 ** hg mv a b / add b b1 / add b w
219 - working to parent:
261 - working to parent:
220 M b
262 M b
221
263
222 diff --git a/b b/b
264 diff --git a/b b/b
223 --- a/b
265 --- a/b
224 +++ b/b
266 +++ b/b
225 @@ -1,3 +1,4 @@
267 @@ -1,3 +1,4 @@
226 a
268 a
227 2
269 2
228 b1
270 b1
229 +w
271 +w
230
272
231 - working to root: --rev 0
273 - working to root: --rev 0
232 A b
274 A b
233 a
275 a
234 R a
276 R a
235
277
236 diff --git a/a b/b
278 diff --git a/a b/b
237 rename from a
279 rename from a
238 rename to b
280 rename to b
239 --- a/a
281 --- a/a
240 +++ b/b
282 +++ b/b
241 @@ -1,1 +1,4 @@
283 @@ -1,1 +1,4 @@
242 a
284 a
243 +2
285 +2
244 +b1
286 +b1
245 +w
287 +w
246
288
247 - working to branch: --rev 2
289 - working to branch: --rev 2
248 A b
290 A b
249 a
291 a
250 R a
292 R a
293 R x/y
251
294
252 diff --git a/a b/b
295 diff --git a/a b/b
253 rename from a
296 rename from a
254 rename to b
297 rename to b
255 --- a/a
298 --- a/a
256 +++ b/b
299 +++ b/b
257 @@ -1,3 +1,4 @@
300 @@ -1,3 +1,4 @@
258 a
301 a
259 -m1
302 -m1
260 -m2
303 -m2
261 +2
304 +2
262 +b1
305 +b1
263 +w
306 +w
307 diff --git a/x/y b/x/y
308 deleted file mode 100644
309 --- a/x/y
310 +++ /dev/null
311 @@ -1,1 +0,0 @@
312 -y1
264
313
265 - root to parent: --rev 0 --rev .
314 - root to parent: --rev 0 --rev .
266 A b
315 A b
267 a
316 a
268 R a
317 R a
269
318
270 diff --git a/a b/b
319 diff --git a/a b/b
271 rename from a
320 rename from a
272 rename to b
321 rename to b
273 --- a/a
322 --- a/a
274 +++ b/b
323 +++ b/b
275 @@ -1,1 +1,3 @@
324 @@ -1,1 +1,3 @@
276 a
325 a
277 +2
326 +2
278 +b1
327 +b1
279
328
280 - parent to root: --rev . --rev 0
329 - parent to root: --rev . --rev 0
281 A a
330 A a
282 b
331 b
283 R b
332 R b
284
333
285 diff --git a/b b/a
334 diff --git a/b b/a
286 rename from b
335 rename from b
287 rename to a
336 rename to a
288 --- a/b
337 --- a/b
289 +++ b/a
338 +++ b/a
290 @@ -1,3 +1,1 @@
339 @@ -1,3 +1,1 @@
291 a
340 a
292 -2
341 -2
293 -b1
342 -b1
294
343
295 - branch to parent: --rev 2 --rev .
344 - branch to parent: --rev 2 --rev .
296 A b
345 A b
297 a
346 a
298 R a
347 R a
348 R x/y
299
349
300 diff --git a/a b/b
350 diff --git a/a b/b
301 rename from a
351 rename from a
302 rename to b
352 rename to b
303 --- a/a
353 --- a/a
304 +++ b/b
354 +++ b/b
305 @@ -1,3 +1,3 @@
355 @@ -1,3 +1,3 @@
306 a
356 a
307 -m1
357 -m1
308 -m2
358 -m2
309 +2
359 +2
310 +b1
360 +b1
361 diff --git a/x/y b/x/y
362 deleted file mode 100644
363 --- a/x/y
364 +++ /dev/null
365 @@ -1,1 +0,0 @@
366 -y1
311
367
312 - parent to branch: --rev . --rev 2
368 - parent to branch: --rev . --rev 2
313 A a
369 A a
314 b
370 b
371 A x/y
315 R b
372 R b
316
373
317 diff --git a/b b/a
374 diff --git a/b b/a
318 rename from b
375 rename from b
319 rename to a
376 rename to a
320 --- a/b
377 --- a/b
321 +++ b/a
378 +++ b/a
322 @@ -1,3 +1,3 @@
379 @@ -1,3 +1,3 @@
323 a
380 a
324 -2
381 -2
325 -b1
382 -b1
326 +m1
383 +m1
327 +m2
384 +m2
385 diff --git a/x/y b/x/y
386 new file mode 100644
387 --- /dev/null
388 +++ b/x/y
389 @@ -0,0 +1,1 @@
390 +y1
328
391
329
392
330 created new head
393 created new head
331 ** single copy **
394 ** single copy **
332 ** hg cp a b / add b b1 / add a w
395 ** hg cp a b / add b b1 / add a w
333 - working to parent:
396 - working to parent:
334 M a
397 M a
335
398
336 diff --git a/a b/a
399 diff --git a/a b/a
337 --- a/a
400 --- a/a
338 +++ b/a
401 +++ b/a
339 @@ -1,2 +1,3 @@
402 @@ -1,2 +1,3 @@
340 a
403 a
341 3
404 3
342 +w
405 +w
343
406
344 - working to root: --rev 0
407 - working to root: --rev 0
345 M a
408 M a
346 A b
409 A b
347 a
410 a
348
411
349 diff --git a/a b/a
412 diff --git a/a b/a
350 --- a/a
413 --- a/a
351 +++ b/a
414 +++ b/a
352 @@ -1,1 +1,3 @@
415 @@ -1,1 +1,3 @@
353 a
416 a
354 +3
417 +3
355 +w
418 +w
356 diff --git a/a b/b
419 diff --git a/a b/b
357 copy from a
420 copy from a
358 copy to b
421 copy to b
359 --- a/a
422 --- a/a
360 +++ b/b
423 +++ b/b
361 @@ -1,1 +1,3 @@
424 @@ -1,1 +1,3 @@
362 a
425 a
363 +3
426 +3
364 +b1
427 +b1
365
428
366 - working to branch: --rev 2
429 - working to branch: --rev 2
367 M a
430 M a
368 A b
431 A b
369 a
432 a
433 R x/y
370
434
371 diff --git a/a b/a
435 diff --git a/a b/a
372 --- a/a
436 --- a/a
373 +++ b/a
437 +++ b/a
374 @@ -1,3 +1,3 @@
438 @@ -1,3 +1,3 @@
375 a
439 a
376 -m1
440 -m1
377 -m2
441 -m2
378 +3
442 +3
379 +w
443 +w
380 diff --git a/a b/b
444 diff --git a/a b/b
381 copy from a
445 copy from a
382 copy to b
446 copy to b
383 --- a/a
447 --- a/a
384 +++ b/b
448 +++ b/b
385 @@ -1,3 +1,3 @@
449 @@ -1,3 +1,3 @@
386 a
450 a
387 -m1
451 -m1
388 -m2
452 -m2
389 +3
453 +3
390 +b1
454 +b1
455 diff --git a/x/y b/x/y
456 deleted file mode 100644
457 --- a/x/y
458 +++ /dev/null
459 @@ -1,1 +0,0 @@
460 -y1
391
461
392 - root to parent: --rev 0 --rev .
462 - root to parent: --rev 0 --rev .
393 M a
463 M a
394 A b
464 A b
395 a
465 a
396
466
397 diff --git a/a b/a
467 diff --git a/a b/a
398 --- a/a
468 --- a/a
399 +++ b/a
469 +++ b/a
400 @@ -1,1 +1,2 @@
470 @@ -1,1 +1,2 @@
401 a
471 a
402 +3
472 +3
403 diff --git a/a b/b
473 diff --git a/a b/b
404 copy from a
474 copy from a
405 copy to b
475 copy to b
406 --- a/a
476 --- a/a
407 +++ b/b
477 +++ b/b
408 @@ -1,1 +1,3 @@
478 @@ -1,1 +1,3 @@
409 a
479 a
410 +3
480 +3
411 +b1
481 +b1
412
482
413 - parent to root: --rev . --rev 0
483 - parent to root: --rev . --rev 0
414 M a
484 M a
415 R b
485 R b
416
486
417 diff --git a/a b/a
487 diff --git a/a b/a
418 --- a/a
488 --- a/a
419 +++ b/a
489 +++ b/a
420 @@ -1,2 +1,1 @@
490 @@ -1,2 +1,1 @@
421 a
491 a
422 -3
492 -3
423 diff --git a/b b/b
493 diff --git a/b b/b
424 deleted file mode 100644
494 deleted file mode 100644
425 --- a/b
495 --- a/b
426 +++ /dev/null
496 +++ /dev/null
427 @@ -1,3 +0,0 @@
497 @@ -1,3 +0,0 @@
428 -a
498 -a
429 -3
499 -3
430 -b1
500 -b1
431
501
432 - branch to parent: --rev 2 --rev .
502 - branch to parent: --rev 2 --rev .
433 M a
503 M a
434 A b
504 A b
435 a
505 a
506 R x/y
436
507
437 diff --git a/a b/a
508 diff --git a/a b/a
438 --- a/a
509 --- a/a
439 +++ b/a
510 +++ b/a
440 @@ -1,3 +1,2 @@
511 @@ -1,3 +1,2 @@
441 a
512 a
442 -m1
513 -m1
443 -m2
514 -m2
444 +3
515 +3
445 diff --git a/a b/b
516 diff --git a/a b/b
446 copy from a
517 copy from a
447 copy to b
518 copy to b
448 --- a/a
519 --- a/a
449 +++ b/b
520 +++ b/b
450 @@ -1,3 +1,3 @@
521 @@ -1,3 +1,3 @@
451 a
522 a
452 -m1
523 -m1
453 -m2
524 -m2
454 +3
525 +3
455 +b1
526 +b1
527 diff --git a/x/y b/x/y
528 deleted file mode 100644
529 --- a/x/y
530 +++ /dev/null
531 @@ -1,1 +0,0 @@
532 -y1
456
533
457 - parent to branch: --rev . --rev 2
534 - parent to branch: --rev . --rev 2
458 M a
535 M a
536 A x/y
459 R b
537 R b
460
538
461 diff --git a/a b/a
539 diff --git a/a b/a
462 --- a/a
540 --- a/a
463 +++ b/a
541 +++ b/a
464 @@ -1,2 +1,3 @@
542 @@ -1,2 +1,3 @@
465 a
543 a
466 -3
544 -3
467 +m1
545 +m1
468 +m2
546 +m2
469 diff --git a/b b/b
547 diff --git a/b b/b
470 deleted file mode 100644
548 deleted file mode 100644
471 --- a/b
549 --- a/b
472 +++ /dev/null
550 +++ /dev/null
473 @@ -1,3 +0,0 @@
551 @@ -1,3 +0,0 @@
474 -a
552 -a
475 -3
553 -3
476 -b1
554 -b1
555 diff --git a/x/y b/x/y
556 new file mode 100644
557 --- /dev/null
558 +++ b/x/y
559 @@ -0,0 +1,1 @@
560 +y1
477
561
478
562
479 created new head
563 created new head
480 ** rename chain **
564 ** rename chain **
481 ** hg mv a b / hg mv b c / hg mv c d
565 ** hg mv a b / hg mv b c / hg mv c d
482 - working to parent:
566 - working to parent:
483 A d
567 A d
484 c
568 c
485 R c
569 R c
486
570
487 diff --git a/c b/d
571 diff --git a/c b/d
488 rename from c
572 rename from c
489 rename to d
573 rename to d
490
574
491 - working to root: --rev 0
575 - working to root: --rev 0
492 A d
576 A d
493 a
577 a
494 R a
578 R a
495
579
496 diff --git a/a b/d
580 diff --git a/a b/d
497 rename from a
581 rename from a
498 rename to d
582 rename to d
499 --- a/a
583 --- a/a
500 +++ b/d
584 +++ b/d
501 @@ -1,1 +1,2 @@
585 @@ -1,1 +1,2 @@
502 a
586 a
503 +4
587 +4
504
588
505 - working to branch: --rev 2
589 - working to branch: --rev 2
506 A d
590 A d
507 a
591 a
508 R a
592 R a
593 R x/y
509
594
510 diff --git a/a b/d
595 diff --git a/a b/d
511 rename from a
596 rename from a
512 rename to d
597 rename to d
513 --- a/a
598 --- a/a
514 +++ b/d
599 +++ b/d
515 @@ -1,3 +1,2 @@
600 @@ -1,3 +1,2 @@
516 a
601 a
517 -m1
602 -m1
518 -m2
603 -m2
519 +4
604 +4
605 diff --git a/x/y b/x/y
606 deleted file mode 100644
607 --- a/x/y
608 +++ /dev/null
609 @@ -1,1 +0,0 @@
610 -y1
520
611
521 - root to parent: --rev 0 --rev .
612 - root to parent: --rev 0 --rev .
522 A c
613 A c
523 a
614 a
524 R a
615 R a
525
616
526 diff --git a/a b/c
617 diff --git a/a b/c
527 rename from a
618 rename from a
528 rename to c
619 rename to c
529 --- a/a
620 --- a/a
530 +++ b/c
621 +++ b/c
531 @@ -1,1 +1,2 @@
622 @@ -1,1 +1,2 @@
532 a
623 a
533 +4
624 +4
534
625
535 - parent to root: --rev . --rev 0
626 - parent to root: --rev . --rev 0
536 A a
627 A a
537 c
628 c
538 R c
629 R c
539
630
540 diff --git a/c b/a
631 diff --git a/c b/a
541 rename from c
632 rename from c
542 rename to a
633 rename to a
543 --- a/c
634 --- a/c
544 +++ b/a
635 +++ b/a
545 @@ -1,2 +1,1 @@
636 @@ -1,2 +1,1 @@
546 a
637 a
547 -4
638 -4
548
639
549 - branch to parent: --rev 2 --rev .
640 - branch to parent: --rev 2 --rev .
550 A c
641 A c
551 a
642 a
552 R a
643 R a
644 R x/y
553
645
554 diff --git a/a b/c
646 diff --git a/a b/c
555 rename from a
647 rename from a
556 rename to c
648 rename to c
557 --- a/a
649 --- a/a
558 +++ b/c
650 +++ b/c
559 @@ -1,3 +1,2 @@
651 @@ -1,3 +1,2 @@
560 a
652 a
561 -m1
653 -m1
562 -m2
654 -m2
563 +4
655 +4
656 diff --git a/x/y b/x/y
657 deleted file mode 100644
658 --- a/x/y
659 +++ /dev/null
660 @@ -1,1 +0,0 @@
661 -y1
564
662
565 - parent to branch: --rev . --rev 2
663 - parent to branch: --rev . --rev 2
566 A a
664 A a
567 c
665 c
666 A x/y
568 R c
667 R c
569
668
570 diff --git a/c b/a
669 diff --git a/c b/a
571 rename from c
670 rename from c
572 rename to a
671 rename to a
573 --- a/c
672 --- a/c
574 +++ b/a
673 +++ b/a
575 @@ -1,2 +1,3 @@
674 @@ -1,2 +1,3 @@
576 a
675 a
577 -4
676 -4
578 +m1
677 +m1
579 +m2
678 +m2
679 diff --git a/x/y b/x/y
680 new file mode 100644
681 --- /dev/null
682 +++ b/x/y
683 @@ -0,0 +1,1 @@
684 +y1
580
685
581
686
582 created new head
687 created new head
583 ** copy chain **
688 ** copy chain **
584 ** hg cp a b / hg cp b c / hg cp c d
689 ** hg cp a b / hg cp b c / hg cp c d
585 - working to parent:
690 - working to parent:
586 A d
691 A d
587 c
692 c
588
693
589 diff --git a/c b/d
694 diff --git a/c b/d
590 copy from c
695 copy from c
591 copy to d
696 copy to d
592
697
593 - working to root: --rev 0
698 - working to root: --rev 0
594 M a
699 M a
595 A b
700 A b
596 a
701 a
597 A c
702 A c
598 a
703 a
599 A d
704 A d
600 a
705 a
601
706
602 diff --git a/a b/a
707 diff --git a/a b/a
603 --- a/a
708 --- a/a
604 +++ b/a
709 +++ b/a
605 @@ -1,1 +1,2 @@
710 @@ -1,1 +1,2 @@
606 a
711 a
607 +5
712 +5
608 diff --git a/a b/b
713 diff --git a/a b/b
609 copy from a
714 copy from a
610 copy to b
715 copy to b
611 --- a/a
716 --- a/a
612 +++ b/b
717 +++ b/b
613 @@ -1,1 +1,2 @@
718 @@ -1,1 +1,2 @@
614 a
719 a
615 +5
720 +5
616 diff --git a/a b/c
721 diff --git a/a b/c
617 copy from a
722 copy from a
618 copy to c
723 copy to c
619 --- a/a
724 --- a/a
620 +++ b/c
725 +++ b/c
621 @@ -1,1 +1,2 @@
726 @@ -1,1 +1,2 @@
622 a
727 a
623 +5
728 +5
624 diff --git a/a b/d
729 diff --git a/a b/d
625 copy from a
730 copy from a
626 copy to d
731 copy to d
627 --- a/a
732 --- a/a
628 +++ b/d
733 +++ b/d
629 @@ -1,1 +1,2 @@
734 @@ -1,1 +1,2 @@
630 a
735 a
631 +5
736 +5
632
737
633 - working to branch: --rev 2
738 - working to branch: --rev 2
634 M a
739 M a
635 A b
740 A b
636 a
741 a
637 A c
742 A c
638 a
743 a
639 A d
744 A d
640 a
745 a
746 R x/y
641
747
642 diff --git a/a b/a
748 diff --git a/a b/a
643 --- a/a
749 --- a/a
644 +++ b/a
750 +++ b/a
645 @@ -1,3 +1,2 @@
751 @@ -1,3 +1,2 @@
646 a
752 a
647 -m1
753 -m1
648 -m2
754 -m2
649 +5
755 +5
650 diff --git a/a b/b
756 diff --git a/a b/b
651 copy from a
757 copy from a
652 copy to b
758 copy to b
653 --- a/a
759 --- a/a
654 +++ b/b
760 +++ b/b
655 @@ -1,3 +1,2 @@
761 @@ -1,3 +1,2 @@
656 a
762 a
657 -m1
763 -m1
658 -m2
764 -m2
659 +5
765 +5
660 diff --git a/a b/c
766 diff --git a/a b/c
661 copy from a
767 copy from a
662 copy to c
768 copy to c
663 --- a/a
769 --- a/a
664 +++ b/c
770 +++ b/c
665 @@ -1,3 +1,2 @@
771 @@ -1,3 +1,2 @@
666 a
772 a
667 -m1
773 -m1
668 -m2
774 -m2
669 +5
775 +5
670 diff --git a/a b/d
776 diff --git a/a b/d
671 copy from a
777 copy from a
672 copy to d
778 copy to d
673 --- a/a
779 --- a/a
674 +++ b/d
780 +++ b/d
675 @@ -1,3 +1,2 @@
781 @@ -1,3 +1,2 @@
676 a
782 a
677 -m1
783 -m1
678 -m2
784 -m2
679 +5
785 +5
786 diff --git a/x/y b/x/y
787 deleted file mode 100644
788 --- a/x/y
789 +++ /dev/null
790 @@ -1,1 +0,0 @@
791 -y1
680
792
681 - root to parent: --rev 0 --rev .
793 - root to parent: --rev 0 --rev .
682 M a
794 M a
683 A b
795 A b
684 a
796 a
685 A c
797 A c
686 a
798 a
687
799
688 diff --git a/a b/a
800 diff --git a/a b/a
689 --- a/a
801 --- a/a
690 +++ b/a
802 +++ b/a
691 @@ -1,1 +1,2 @@
803 @@ -1,1 +1,2 @@
692 a
804 a
693 +5
805 +5
694 diff --git a/a b/b
806 diff --git a/a b/b
695 copy from a
807 copy from a
696 copy to b
808 copy to b
697 --- a/a
809 --- a/a
698 +++ b/b
810 +++ b/b
699 @@ -1,1 +1,2 @@
811 @@ -1,1 +1,2 @@
700 a
812 a
701 +5
813 +5
702 diff --git a/a b/c
814 diff --git a/a b/c
703 copy from a
815 copy from a
704 copy to c
816 copy to c
705 --- a/a
817 --- a/a
706 +++ b/c
818 +++ b/c
707 @@ -1,1 +1,2 @@
819 @@ -1,1 +1,2 @@
708 a
820 a
709 +5
821 +5
710
822
711 - parent to root: --rev . --rev 0
823 - parent to root: --rev . --rev 0
712 M a
824 M a
713 R b
825 R b
714 R c
826 R c
715
827
716 diff --git a/a b/a
828 diff --git a/a b/a
717 --- a/a
829 --- a/a
718 +++ b/a
830 +++ b/a
719 @@ -1,2 +1,1 @@
831 @@ -1,2 +1,1 @@
720 a
832 a
721 -5
833 -5
722 diff --git a/b b/b
834 diff --git a/b b/b
723 deleted file mode 100644
835 deleted file mode 100644
724 --- a/b
836 --- a/b
725 +++ /dev/null
837 +++ /dev/null
726 @@ -1,2 +0,0 @@
838 @@ -1,2 +0,0 @@
727 -a
839 -a
728 -5
840 -5
729 diff --git a/c b/c
841 diff --git a/c b/c
730 deleted file mode 100644
842 deleted file mode 100644
731 --- a/c
843 --- a/c
732 +++ /dev/null
844 +++ /dev/null
733 @@ -1,2 +0,0 @@
845 @@ -1,2 +0,0 @@
734 -a
846 -a
735 -5
847 -5
736
848
737 - branch to parent: --rev 2 --rev .
849 - branch to parent: --rev 2 --rev .
738 M a
850 M a
739 A b
851 A b
740 a
852 a
741 A c
853 A c
742 a
854 a
855 R x/y
743
856
744 diff --git a/a b/a
857 diff --git a/a b/a
745 --- a/a
858 --- a/a
746 +++ b/a
859 +++ b/a
747 @@ -1,3 +1,2 @@
860 @@ -1,3 +1,2 @@
748 a
861 a
749 -m1
862 -m1
750 -m2
863 -m2
751 +5
864 +5
752 diff --git a/a b/b
865 diff --git a/a b/b
753 copy from a
866 copy from a
754 copy to b
867 copy to b
755 --- a/a
868 --- a/a
756 +++ b/b
869 +++ b/b
757 @@ -1,3 +1,2 @@
870 @@ -1,3 +1,2 @@
758 a
871 a
759 -m1
872 -m1
760 -m2
873 -m2
761 +5
874 +5
762 diff --git a/a b/c
875 diff --git a/a b/c
763 copy from a
876 copy from a
764 copy to c
877 copy to c
765 --- a/a
878 --- a/a
766 +++ b/c
879 +++ b/c
767 @@ -1,3 +1,2 @@
880 @@ -1,3 +1,2 @@
768 a
881 a
769 -m1
882 -m1
770 -m2
883 -m2
771 +5
884 +5
885 diff --git a/x/y b/x/y
886 deleted file mode 100644
887 --- a/x/y
888 +++ /dev/null
889 @@ -1,1 +0,0 @@
890 -y1
772
891
773 - parent to branch: --rev . --rev 2
892 - parent to branch: --rev . --rev 2
774 M a
893 M a
894 A x/y
775 R b
895 R b
776 R c
896 R c
777
897
778 diff --git a/a b/a
898 diff --git a/a b/a
779 --- a/a
899 --- a/a
780 +++ b/a
900 +++ b/a
781 @@ -1,2 +1,3 @@
901 @@ -1,2 +1,3 @@
782 a
902 a
783 -5
903 -5
784 +m1
904 +m1
785 +m2
905 +m2
786 diff --git a/b b/b
906 diff --git a/b b/b
787 deleted file mode 100644
907 deleted file mode 100644
788 --- a/b
908 --- a/b
789 +++ /dev/null
909 +++ /dev/null
790 @@ -1,2 +0,0 @@
910 @@ -1,2 +0,0 @@
791 -a
911 -a
792 -5
912 -5
793 diff --git a/c b/c
913 diff --git a/c b/c
794 deleted file mode 100644
914 deleted file mode 100644
795 --- a/c
915 --- a/c
796 +++ /dev/null
916 +++ /dev/null
797 @@ -1,2 +0,0 @@
917 @@ -1,2 +0,0 @@
798 -a
918 -a
799 -5
919 -5
920 diff --git a/x/y b/x/y
921 new file mode 100644
922 --- /dev/null
923 +++ b/x/y
924 @@ -0,0 +1,1 @@
925 +y1
800
926
801
927
802 created new head
928 created new head
803 ** circular rename **
929 ** circular rename **
804 ** add a a1 / hg mv a b / hg mv b a
930 ** add a a1 / hg mv a b / hg mv b a
805 - working to parent:
931 - working to parent:
806 A a
932 A a
807 b
933 b
808 R b
934 R b
809
935
810 diff --git a/b b/a
936 diff --git a/b b/a
811 rename from b
937 rename from b
812 rename to a
938 rename to a
813
939
814 - working to root: --rev 0
940 - working to root: --rev 0
815 M a
941 M a
816
942
817 diff --git a/a b/a
943 diff --git a/a b/a
818 --- a/a
944 --- a/a
819 +++ b/a
945 +++ b/a
820 @@ -1,1 +1,3 @@
946 @@ -1,1 +1,3 @@
821 a
947 a
822 +6
948 +6
823 +a1
949 +a1
824
950
825 - working to branch: --rev 2
951 - working to branch: --rev 2
826 M a
952 M a
953 R x/y
827
954
828 diff --git a/a b/a
955 diff --git a/a b/a
829 --- a/a
956 --- a/a
830 +++ b/a
957 +++ b/a
831 @@ -1,3 +1,3 @@
958 @@ -1,3 +1,3 @@
832 a
959 a
833 -m1
960 -m1
834 -m2
961 -m2
835 +6
962 +6
836 +a1
963 +a1
964 diff --git a/x/y b/x/y
965 deleted file mode 100644
966 --- a/x/y
967 +++ /dev/null
968 @@ -1,1 +0,0 @@
969 -y1
837
970
838 - root to parent: --rev 0 --rev .
971 - root to parent: --rev 0 --rev .
839 A b
972 A b
840 a
973 a
841 R a
974 R a
842
975
843 diff --git a/a b/b
976 diff --git a/a b/b
844 rename from a
977 rename from a
845 rename to b
978 rename to b
846 --- a/a
979 --- a/a
847 +++ b/b
980 +++ b/b
848 @@ -1,1 +1,3 @@
981 @@ -1,1 +1,3 @@
849 a
982 a
850 +6
983 +6
851 +a1
984 +a1
852
985
853 - parent to root: --rev . --rev 0
986 - parent to root: --rev . --rev 0
854 A a
987 A a
855 b
988 b
856 R b
989 R b
857
990
858 diff --git a/b b/a
991 diff --git a/b b/a
859 rename from b
992 rename from b
860 rename to a
993 rename to a
861 --- a/b
994 --- a/b
862 +++ b/a
995 +++ b/a
863 @@ -1,3 +1,1 @@
996 @@ -1,3 +1,1 @@
864 a
997 a
865 -6
998 -6
866 -a1
999 -a1
867
1000
868 - branch to parent: --rev 2 --rev .
1001 - branch to parent: --rev 2 --rev .
869 A b
1002 A b
870 a
1003 a
871 R a
1004 R a
1005 R x/y
872
1006
873 diff --git a/a b/b
1007 diff --git a/a b/b
874 rename from a
1008 rename from a
875 rename to b
1009 rename to b
876 --- a/a
1010 --- a/a
877 +++ b/b
1011 +++ b/b
878 @@ -1,3 +1,3 @@
1012 @@ -1,3 +1,3 @@
879 a
1013 a
880 -m1
1014 -m1
881 -m2
1015 -m2
882 +6
1016 +6
883 +a1
1017 +a1
1018 diff --git a/x/y b/x/y
1019 deleted file mode 100644
1020 --- a/x/y
1021 +++ /dev/null
1022 @@ -1,1 +0,0 @@
1023 -y1
884
1024
885 - parent to branch: --rev . --rev 2
1025 - parent to branch: --rev . --rev 2
886 A a
1026 A a
887 b
1027 b
1028 A x/y
888 R b
1029 R b
889
1030
890 diff --git a/b b/a
1031 diff --git a/b b/a
891 rename from b
1032 rename from b
892 rename to a
1033 rename to a
893 --- a/b
1034 --- a/b
894 +++ b/a
1035 +++ b/a
895 @@ -1,3 +1,3 @@
1036 @@ -1,3 +1,3 @@
896 a
1037 a
897 -6
1038 -6
898 -a1
1039 -a1
899 +m1
1040 +m1
900 +m2
1041 +m2
1042 diff --git a/x/y b/x/y
1043 new file mode 100644
1044 --- /dev/null
1045 +++ b/x/y
1046 @@ -0,0 +1,1 @@
1047 +y1
901
1048
902
1049
1050 created new head
1051 moving x/x to y/x
1052 ** directory move **
1053 ** hg mv x y / add y/x x1 / add y/x x2
1054 - working to parent:
1055 M y/x
1056
1057 diff --git a/y/x b/y/x
1058 --- a/y/x
1059 +++ b/y/x
1060 @@ -1,2 +1,3 @@
1061 x
1062 x1
1063 +x2
1064
1065 - working to root: --rev 0
1066 M a
1067 A y/x
1068 x/x
1069 R x/x
1070
1071 diff --git a/a b/a
1072 --- a/a
1073 +++ b/a
1074 @@ -1,1 +1,2 @@
1075 a
1076 +7
1077 diff --git a/x/x b/y/x
1078 rename from x/x
1079 rename to y/x
1080 --- a/x/x
1081 +++ b/y/x
1082 @@ -1,1 +1,3 @@
1083 x
1084 +x1
1085 +x2
1086
1087 - working to branch: --rev 2
1088 M a
1089 A y/x
1090 x/x
1091 R x/x
1092 R x/y
1093
1094 diff --git a/a b/a
1095 --- a/a
1096 +++ b/a
1097 @@ -1,3 +1,2 @@
1098 a
1099 -m1
1100 -m2
1101 +7
1102 diff --git a/x/y b/x/y
1103 deleted file mode 100644
1104 --- a/x/y
1105 +++ /dev/null
1106 @@ -1,1 +0,0 @@
1107 -y1
1108 diff --git a/x/x b/y/x
1109 rename from x/x
1110 rename to y/x
1111 --- a/x/x
1112 +++ b/y/x
1113 @@ -1,1 +1,3 @@
1114 x
1115 +x1
1116 +x2
1117
1118 - root to parent: --rev 0 --rev .
1119 M a
1120 A y/x
1121 x/x
1122 R x/x
1123
1124 diff --git a/a b/a
1125 --- a/a
1126 +++ b/a
1127 @@ -1,1 +1,2 @@
1128 a
1129 +7
1130 diff --git a/x/x b/y/x
1131 rename from x/x
1132 rename to y/x
1133 --- a/x/x
1134 +++ b/y/x
1135 @@ -1,1 +1,2 @@
1136 x
1137 +x1
1138
1139 - parent to root: --rev . --rev 0
1140 M a
1141 A x/x
1142 y/x
1143 R y/x
1144
1145 diff --git a/a b/a
1146 --- a/a
1147 +++ b/a
1148 @@ -1,2 +1,1 @@
1149 a
1150 -7
1151 diff --git a/y/x b/x/x
1152 rename from y/x
1153 rename to x/x
1154 --- a/y/x
1155 +++ b/x/x
1156 @@ -1,2 +1,1 @@
1157 x
1158 -x1
1159
1160 - branch to parent: --rev 2 --rev .
1161 M a
1162 A y/x
1163 x/x
1164 R x/x
1165 R x/y
1166
1167 diff --git a/a b/a
1168 --- a/a
1169 +++ b/a
1170 @@ -1,3 +1,2 @@
1171 a
1172 -m1
1173 -m2
1174 +7
1175 diff --git a/x/y b/x/y
1176 deleted file mode 100644
1177 --- a/x/y
1178 +++ /dev/null
1179 @@ -1,1 +0,0 @@
1180 -y1
1181 diff --git a/x/x b/y/x
1182 rename from x/x
1183 rename to y/x
1184 --- a/x/x
1185 +++ b/y/x
1186 @@ -1,1 +1,2 @@
1187 x
1188 +x1
1189
1190 - parent to branch: --rev . --rev 2
1191 M a
1192 A x/x
1193 y/x
1194 A x/y
1195 R y/x
1196
1197 diff --git a/a b/a
1198 --- a/a
1199 +++ b/a
1200 @@ -1,2 +1,3 @@
1201 a
1202 -7
1203 +m1
1204 +m2
1205 diff --git a/y/x b/x/x
1206 rename from y/x
1207 rename to x/x
1208 --- a/y/x
1209 +++ b/x/x
1210 @@ -1,2 +1,1 @@
1211 x
1212 -x1
1213 diff --git a/x/y b/x/y
1214 new file mode 100644
1215 --- /dev/null
1216 +++ b/x/y
1217 @@ -0,0 +1,1 @@
1218 +y1
1219
1220
General Comments 0
You need to be logged in to leave comments. Login now