##// END OF EJS Templates
merge: merge file flags together with file content...
Mads Kiilerich -
r18338:384df4db default
parent child Browse files
Show More
@@ -45,11 +45,11 b' class mergestate(object):'
45 f.write("\0".join([d] + v) + "\n")
45 f.write("\0".join([d] + v) + "\n")
46 f.close()
46 f.close()
47 self._dirty = False
47 self._dirty = False
48 def add(self, fcl, fco, fca, fd, flags):
48 def add(self, fcl, fco, fca, fd):
49 hash = util.sha1(fcl.path()).hexdigest()
49 hash = util.sha1(fcl.path()).hexdigest()
50 self._repo.opener.write("merge/" + hash, fcl.data())
50 self._repo.opener.write("merge/" + hash, fcl.data())
51 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
51 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
52 hex(fca.filenode()), fco.path(), flags]
52 hex(fca.filenode()), fco.path(), fcl.flags()]
53 self._dirty = True
53 self._dirty = True
54 def __contains__(self, dfile):
54 def __contains__(self, dfile):
55 return dfile in self._state
55 return dfile in self._state
@@ -67,12 +67,22 b' class mergestate(object):'
67 if self[dfile] == 'r':
67 if self[dfile] == 'r':
68 return 0
68 return 0
69 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
69 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
70 fcd = wctx[dfile]
71 fco = octx[ofile]
72 fca = self._repo.filectx(afile, fileid=anode)
73 # "premerge" x flags
74 flo = fco.flags()
75 fla = fca.flags()
76 if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
77 if fca.node() == nullid:
78 self._repo.ui.warn(_('warning: cannot merge flags for %s\n') %
79 afile)
80 elif flags == fla:
81 flags = flo
82 # restore local
70 f = self._repo.opener("merge/" + hash)
83 f = self._repo.opener("merge/" + hash)
71 self._repo.wwrite(dfile, f.read(), flags)
84 self._repo.wwrite(dfile, f.read(), flags)
72 f.close()
85 f.close()
73 fcd = wctx[dfile]
74 fco = octx[ofile]
75 fca = self._repo.filectx(afile, fileid=anode)
76 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
86 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
77 if r is None:
87 if r is None:
78 # no real conflict
88 # no real conflict
@@ -183,32 +193,6 b' def manifestmerge(repo, p1, p2, pa, over'
183 partial = function to filter file lists
193 partial = function to filter file lists
184 """
194 """
185
195
186 def fmerge(f, f2, fa):
187 """merge flags"""
188 a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
189 if m == n: # flags agree
190 return m # unchanged
191 if m and n and not a: # flags set, don't agree, differ from parent
192 r = repo.ui.promptchoice(
193 _(" conflicting flags for %s\n"
194 "(n)one, e(x)ec or sym(l)ink?") % f,
195 (_("&None"), _("E&xec"), _("Sym&link")), 0)
196 if r == 1:
197 return "x" # Exec
198 if r == 2:
199 return "l" # Symlink
200 return ""
201 if m and m != a: # changed from a to m
202 return m
203 if n and n != a: # changed from a to n
204 if (n == 'l' or a == 'l') and m1.get(f) != ma.get(f):
205 # can't automatically merge symlink flag when there
206 # are file-level conflicts here, let filemerge take
207 # care of it
208 return m
209 return n
210 return '' # flag was cleared
211
212 def act(msg, m, f, *args):
196 def act(msg, m, f, *args):
213 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
197 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
214 actions.append((f, m) + args)
198 actions.append((f, m) + args)
@@ -248,17 +232,25 b' def manifestmerge(repo, p1, p2, pa, over'
248 if partial and not partial(f):
232 if partial and not partial(f):
249 continue
233 continue
250 if f in m2:
234 if f in m2:
251 rflags = fmerge(f, f, f)
235 n2 = m2[f]
236 fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f)
237 nol = 'l' not in fl1 + fl2 + fla
252 a = ma.get(f, nullid)
238 a = ma.get(f, nullid)
253 if n == m2[f] or m2[f] == a: # same or local newer
239 if n == n2 and fl1 == fl2:
254 # is file locally modified or flags need changing?
240 pass # same - keep local
255 # dirstate flags may need to be made current
241 elif n2 == a and fl2 == fla:
256 if m1.flags(f) != rflags or n[20:]:
242 pass # remote unchanged - keep local
257 act("update permissions", "e", f, rflags)
243 elif n == a and fl1 == fla: # local unchanged - use remote
258 elif n == a: # remote newer
244 if n == n2: # optimization: keep local content
259 act("remote is newer", "g", f, rflags)
245 act("update permissions", "e", f, fl2)
260 else: # both changed
246 else:
261 act("versions differ", "m", f, f, f, rflags, False)
247 act("remote is newer", "g", f, fl2)
248 elif nol and n2 == a: # remote only changed 'x'
249 act("update permissions", "e", f, fl2)
250 elif nol and n == a: # local only changed 'x'
251 act("remote is newer", "g", f, fl)
252 else: # both changed something
253 act("versions differ", "m", f, f, f, False)
262 elif f in copied: # files we'll deal with on m2 side
254 elif f in copied: # files we'll deal with on m2 side
263 pass
255 pass
264 elif f in movewithdir: # directory rename
256 elif f in movewithdir: # directory rename
@@ -267,8 +259,7 b' def manifestmerge(repo, p1, p2, pa, over'
267 m1.flags(f))
259 m1.flags(f))
268 elif f in copy: # case 2 A,B/B/B or case 4,21 A/B/B
260 elif f in copy: # case 2 A,B/B/B or case 4,21 A/B/B
269 f2 = copy[f]
261 f2 = copy[f]
270 act("local copied/moved to " + f2, "m", f, f2, f,
262 act("local copied/moved to " + f2, "m", f, f2, f, False)
271 fmerge(f, f2, f2), False)
272 elif f in ma: # clean, a different, no remote
263 elif f in ma: # clean, a different, no remote
273 if n != ma[f]:
264 if n != ma[f]:
274 if repo.ui.promptchoice(
265 if repo.ui.promptchoice(
@@ -296,16 +287,15 b' def manifestmerge(repo, p1, p2, pa, over'
296 f2 = copy[f]
287 f2 = copy[f]
297 if f2 in m2: # rename case 1, A/A,B/A
288 if f2 in m2: # rename case 1, A/A,B/A
298 act("remote copied to " + f, "m",
289 act("remote copied to " + f, "m",
299 f2, f, f, fmerge(f2, f, f2), False)
290 f2, f, f, False)
300 else: # case 3,20 A/B/A
291 else: # case 3,20 A/B/A
301 act("remote moved to " + f, "m",
292 act("remote moved to " + f, "m",
302 f2, f, f, fmerge(f2, f, f2), True)
293 f2, f, f, True)
303 elif f not in ma:
294 elif f not in ma:
304 if (not overwrite
295 if (not overwrite
305 and _checkunknownfile(repo, p1, p2, f)):
296 and _checkunknownfile(repo, p1, p2, f)):
306 rflags = fmerge(f, f, f)
307 act("remote differs from untracked local",
297 act("remote differs from untracked local",
308 "m", f, f, f, rflags, False)
298 "m", f, f, f, False)
309 else:
299 else:
310 act("remote created", "g", f, m2.flags(f))
300 act("remote created", "g", f, m2.flags(f))
311 elif n != ma[f]:
301 elif n != ma[f]:
@@ -341,7 +331,7 b' def applyupdates(repo, actions, wctx, mc'
341 for a in actions:
331 for a in actions:
342 f, m = a[:2]
332 f, m = a[:2]
343 if m == "m": # merge
333 if m == "m": # merge
344 f2, fd, flags, move = a[2:]
334 f2, fd, move = a[2:]
345 if fd == '.hgsubstate': # merged internally
335 if fd == '.hgsubstate': # merged internally
346 continue
336 continue
347 repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd))
337 repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd))
@@ -356,7 +346,7 b' def applyupdates(repo, actions, wctx, mc'
356 fca = fcl.ancestor(fco, actx)
346 fca = fcl.ancestor(fco, actx)
357 if not fca:
347 if not fca:
358 fca = repo.filectx(f, fileid=nullrev)
348 fca = repo.filectx(f, fileid=nullrev)
359 ms.add(fcl, fco, fca, fd, flags)
349 ms.add(fcl, fco, fca, fd)
360 if f != fd and move:
350 if f != fd and move:
361 moves.append(f)
351 moves.append(f)
362
352
@@ -390,7 +380,7 b' def applyupdates(repo, actions, wctx, mc'
390 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
380 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
391 overwrite)
381 overwrite)
392 continue
382 continue
393 f2, fd, flags, move = a[2:]
383 f2, fd, move = a[2:]
394 audit(fd)
384 audit(fd)
395 r = ms.resolve(fd, wctx, mctx)
385 r = ms.resolve(fd, wctx, mctx)
396 if r is not None and r > 0:
386 if r is not None and r > 0:
@@ -484,7 +474,7 b' def recordupdates(repo, actions, branchm'
484 else:
474 else:
485 repo.dirstate.normal(f)
475 repo.dirstate.normal(f)
486 elif m == "m": # merge
476 elif m == "m": # merge
487 f2, fd, flag, move = a[2:]
477 f2, fd, move = a[2:]
488 if branchmerge:
478 if branchmerge:
489 # We've done a branch merge, mark this file as merged
479 # We've done a branch merge, mark this file as merged
490 # so that we properly record the merger later
480 # so that we properly record the merger later
@@ -34,16 +34,28 b' Symlink is local parent, executable is o'
34 resolving manifests
34 resolving manifests
35 overwrite: False, partial: False
35 overwrite: False, partial: False
36 ancestor: c334dc3be0da, local: 521a1e40188f+, remote: 3574f3e69b1c
36 ancestor: c334dc3be0da, local: 521a1e40188f+, remote: 3574f3e69b1c
37 conflicting flags for a
37 a: versions differ -> m
38 (n)one, e(x)ec or sym(l)ink? n
38 preserving a for resolve of a
39 a: update permissions -> e
40 updating: a 1/1 files (100.00%)
39 updating: a 1/1 files (100.00%)
41 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
40 picked tool 'internal:merge' for a (binary False symlink True)
42 (branch merge, don't forget to commit)
41 merging a
42 my a@521a1e40188f+ other a@3574f3e69b1c ancestor a@c334dc3be0da
43 warning: internal:merge cannot merge symlinks for a
44 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
45 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
46 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
47 [1]
43
48
44 $ tellmeabout a
49 $ tellmeabout a
45 a is a plain file with content:
50 a is a symlink:
46 symlink (no-eol)
51 a -> symlink
52 $ hg resolve a --tool internal:other
53 $ tellmeabout a
54 a is an executable file with content:
55 a
56 $ hg st
57 M a
58 ? a.orig
47
59
48 Symlink is other parent, executable is local:
60 Symlink is other parent, executable is local:
49
61
@@ -55,17 +67,21 b' Symlink is other parent, executable is l'
55 resolving manifests
67 resolving manifests
56 overwrite: False, partial: False
68 overwrite: False, partial: False
57 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
69 ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
58 conflicting flags for a
70 a: versions differ -> m
59 (n)one, e(x)ec or sym(l)ink? n
71 preserving a for resolve of a
60 a: remote is newer -> g
61 updating: a 1/1 files (100.00%)
72 updating: a 1/1 files (100.00%)
62 getting a
73 picked tool 'internal:merge' for a (binary False symlink True)
63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
74 merging a
64 (branch merge, don't forget to commit)
75 my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
76 warning: internal:merge cannot merge symlinks for a
77 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
78 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
79 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
80 [1]
65
81
66 $ tellmeabout a
82 $ tellmeabout a
67 a is a plain file with content:
83 a is an executable file with content:
68 symlink (no-eol)
84 a
69
85
70 Update to link without local change should get us a symlink (issue3316):
86 Update to link without local change should get us a symlink (issue3316):
71
87
@@ -74,6 +90,7 b' Update to link without local change shou'
74 $ hg up
90 $ hg up
75 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 $ hg st
92 $ hg st
93 ? a.orig
77
94
78 Update to link with local change should cause a merge prompt (issue3200):
95 Update to link with local change should cause a merge prompt (issue3200):
79
96
@@ -119,18 +136,24 b' where that was what happened.'
119 $ ln -s base f
136 $ ln -s base f
120 $ hg ci -qm2
137 $ hg ci -qm2
121 $ hg merge
138 $ hg merge
122 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
139 merging f
123 (branch merge, don't forget to commit)
140 warning: internal:merge cannot merge symlinks for f
141 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
142 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
143 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
144 [1]
124 $ tellmeabout f
145 $ tellmeabout f
125 f is a symlink:
146 f is a symlink:
126 f -> file
147 f -> base
127 content
128
129
148
130 $ hg up -Cqr1
149 $ hg up -Cqr1
131 $ hg merge
150 $ hg merge
132 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
151 merging f
133 (branch merge, don't forget to commit)
152 warning: internal:merge cannot merge symlinks for f
153 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
154 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
155 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
156 [1]
134 $ tellmeabout f
157 $ tellmeabout f
135 f is a plain file with content:
158 f is a plain file with content:
136 file
159 file
@@ -152,19 +175,27 b" Test removed 'x' flag merged with change"
152 $ ln -s dangling f
175 $ ln -s dangling f
153 $ hg ci -qm2
176 $ hg ci -qm2
154 $ hg merge
177 $ hg merge
155 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
178 merging f
156 (branch merge, don't forget to commit)
179 warning: internal:merge cannot merge symlinks for f
180 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
181 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
182 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
183 [1]
157 $ tellmeabout f
184 $ tellmeabout f
158 f is a symlink:
185 f is a symlink:
159 f -> dangling
186 f -> dangling
160
187
161 $ hg up -Cqr1
188 $ hg up -Cqr1
162 $ hg merge
189 $ hg merge
163 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 merging f
164 (branch merge, don't forget to commit)
191 warning: internal:merge cannot merge symlinks for f
192 merging f incomplete! (edit conflicts, then use 'hg resolve --mark')
193 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
194 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
195 [1]
165 $ tellmeabout f
196 $ tellmeabout f
166 f is a symlink:
197 f is a plain file with content:
167 f -> dangling
198 f
168
199
169 $ cd ..
200 $ cd ..
170
201
@@ -210,13 +241,10 b' h: l vs l, different'
210 $ hg ci -Aqm2
241 $ hg ci -Aqm2
211
242
212 $ hg merge
243 $ hg merge
213 conflicting flags for e
214 (n)one, e(x)ec or sym(l)ink? n
215 conflicting flags for d
216 (n)one, e(x)ec or sym(l)ink? n
217 merging a
244 merging a
218 warning: conflicts during merge.
245 warning: conflicts during merge.
219 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
246 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
247 warning: cannot merge flags for b
220 merging b
248 merging b
221 warning: conflicts during merge.
249 warning: conflicts during merge.
222 merging b incomplete! (edit conflicts, then use 'hg resolve --mark')
250 merging b incomplete! (edit conflicts, then use 'hg resolve --mark')
@@ -229,7 +257,7 b' h: l vs l, different'
229 merging h
257 merging h
230 warning: internal:merge cannot merge symlinks for h
258 warning: internal:merge cannot merge symlinks for h
231 merging h incomplete! (edit conflicts, then use 'hg resolve --mark')
259 merging h incomplete! (edit conflicts, then use 'hg resolve --mark')
232 2 files updated, 0 files merged, 0 files removed, 5 files unresolved
260 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
233 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
261 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
234 [1]
262 [1]
235 $ hg resolve -l
263 $ hg resolve -l
@@ -246,21 +274,21 b' h: l vs l, different'
246 1
274 1
247 >>>>>>> other
275 >>>>>>> other
248 $ tellmeabout b
276 $ tellmeabout b
249 b is an executable file with content:
277 b is a plain file with content:
250 <<<<<<< local
278 <<<<<<< local
251 2
279 2
252 =======
280 =======
253 1
281 1
254 >>>>>>> other
282 >>>>>>> other
255 $ tellmeabout c
283 $ tellmeabout c
256 c is an executable file with content:
284 c is a plain file with content:
257 x
285 x
258 $ tellmeabout d
286 $ tellmeabout d
259 d is a plain file with content:
287 d is a symlink:
260 2 (no-eol)
288 d -> 2
261 $ tellmeabout e
289 $ tellmeabout e
262 e is a plain file with content:
290 e is a symlink:
263 x (no-eol)
291 e -> x
264 $ tellmeabout f
292 $ tellmeabout f
265 f is a symlink:
293 f is a symlink:
266 f -> 2
294 f -> 2
@@ -273,13 +301,10 b' h: l vs l, different'
273
301
274 $ hg up -Cqr1
302 $ hg up -Cqr1
275 $ hg merge
303 $ hg merge
276 conflicting flags for e
277 (n)one, e(x)ec or sym(l)ink? n
278 conflicting flags for d
279 (n)one, e(x)ec or sym(l)ink? n
280 merging a
304 merging a
281 warning: conflicts during merge.
305 warning: conflicts during merge.
282 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
306 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
307 warning: cannot merge flags for b
283 merging b
308 merging b
284 warning: conflicts during merge.
309 warning: conflicts during merge.
285 merging b incomplete! (edit conflicts, then use 'hg resolve --mark')
310 merging b incomplete! (edit conflicts, then use 'hg resolve --mark')
@@ -292,7 +317,7 b' h: l vs l, different'
292 merging h
317 merging h
293 warning: internal:merge cannot merge symlinks for h
318 warning: internal:merge cannot merge symlinks for h
294 merging h incomplete! (edit conflicts, then use 'hg resolve --mark')
319 merging h incomplete! (edit conflicts, then use 'hg resolve --mark')
295 1 files updated, 0 files merged, 0 files removed, 5 files unresolved
320 3 files updated, 0 files merged, 0 files removed, 5 files unresolved
296 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
321 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
297 [1]
322 [1]
298 $ tellmeabout a
323 $ tellmeabout a
@@ -310,13 +335,13 b' h: l vs l, different'
310 2
335 2
311 >>>>>>> other
336 >>>>>>> other
312 $ tellmeabout c
337 $ tellmeabout c
313 c is an executable file with content:
338 c is a plain file with content:
314 x
339 x
315 $ tellmeabout d
340 $ tellmeabout d
316 d is a plain file with content:
341 d is an executable file with content:
317 1
342 1
318 $ tellmeabout e
343 $ tellmeabout e
319 e is a plain file with content:
344 e is an executable file with content:
320 x (no-eol)
345 x (no-eol)
321 $ tellmeabout f
346 $ tellmeabout f
322 f is a plain file with content:
347 f is a plain file with content:
General Comments 0
You need to be logged in to leave comments. Login now