11 demandload(globals(), "errno util os tempfile") |
11 demandload(globals(), "errno util os tempfile") |
12 |
12 |
13 def filemerge(repo, fw, fo, wctx, mctx): |
13 def filemerge(repo, fw, fo, wctx, mctx): |
14 """perform a 3-way merge in the working directory |
14 """perform a 3-way merge in the working directory |
15 |
15 |
16 fw = filename in the working directory and first parent |
16 fw = filename in the working directory |
17 fo = filename in other parent |
17 fo = filename in other parent |
18 wctx, mctx = working and merge changecontexts |
18 wctx, mctx = working and merge changecontexts |
19 |
|
20 TODO: |
|
21 if fw is copied in the working directory, we get confused |
|
22 implement move and fd |
|
23 """ |
19 """ |
24 |
20 |
25 def temp(prefix, ctx): |
21 def temp(prefix, ctx): |
26 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix) |
22 pre = "%s~%s." % (os.path.basename(ctx.path()), prefix) |
27 (fd, name) = tempfile.mkstemp(prefix=pre) |
23 (fd, name) = tempfile.mkstemp(prefix=pre) |
62 os.unlink(b) |
58 os.unlink(b) |
63 os.unlink(c) |
59 os.unlink(c) |
64 return r |
60 return r |
65 |
61 |
66 def checkunknown(wctx, mctx): |
62 def checkunknown(wctx, mctx): |
67 """ |
63 "check for collisions between unknown files and files in mctx" |
68 check for collisions between unknown files and files in m2 |
|
69 """ |
|
70 man = mctx.manifest() |
64 man = mctx.manifest() |
71 for f in wctx.unknown(): |
65 for f in wctx.unknown(): |
72 if f in man: |
66 if f in man: |
73 if mctx.filectx(f).cmp(wctx.filectx(f).data()): |
67 if mctx.filectx(f).cmp(wctx.filectx(f).data()): |
74 raise util.Abort(_("'%s' already exists in the working" |
68 raise util.Abort(_("'%s' already exists in the working" |
92 action.append((f, "f")) |
86 action.append((f, "f")) |
93 |
87 |
94 return action |
88 return action |
95 |
89 |
96 def nonoverlap(d1, d2): |
90 def nonoverlap(d1, d2): |
97 """ |
91 "Return list of elements in d1 not in d2" |
98 Return list of elements in d1 not in d2 |
|
99 """ |
|
100 |
92 |
101 l = [] |
93 l = [] |
102 for d in d1: |
94 for d in d1: |
103 if d not in d2: |
95 if d not in d2: |
104 l.append(d) |
96 l.append(d) |
105 |
97 |
106 l.sort() |
98 l.sort() |
107 return l |
99 return l |
108 |
100 |
109 def findold(fctx, limit): |
101 def findold(fctx, limit): |
110 """ |
102 "find files that path was copied from, back to linkrev limit" |
111 find files that path was copied from, back to linkrev limit |
|
112 """ |
|
113 |
103 |
114 old = {} |
104 old = {} |
115 orig = fctx.path() |
105 orig = fctx.path() |
116 visit = [fctx] |
106 visit = [fctx] |
117 while visit: |
107 while visit: |
172 |
162 |
173 return copy |
163 return copy |
174 |
164 |
175 def manifestmerge(repo, p1, p2, pa, overwrite, partial): |
165 def manifestmerge(repo, p1, p2, pa, overwrite, partial): |
176 """ |
166 """ |
177 Merge manifest m1 with m2 using ancestor ma and generate merge action list |
167 Merge p1 and p2 with ancestor ma and generate merge action list |
|
168 |
|
169 overwrite = whether we clobber working files |
|
170 partial = function to filter file lists |
178 """ |
171 """ |
179 |
172 |
180 repo.ui.note(_("resolving manifests\n")) |
173 repo.ui.note(_("resolving manifests\n")) |
181 repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial))) |
174 repo.ui.debug(_(" overwrite %s partial %s\n") % (overwrite, bool(partial))) |
182 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2)) |
175 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % (pa, p1, p2)) |
273 act("remote created", "g", f, m2.execf(f)) |
266 act("remote created", "g", f, m2.execf(f)) |
274 |
267 |
275 return action |
268 return action |
276 |
269 |
277 def applyupdates(repo, action, wctx, mctx): |
270 def applyupdates(repo, action, wctx, mctx): |
|
271 "apply the merge action list to the working directory" |
|
272 |
278 updated, merged, removed, unresolved = 0, 0, 0, 0 |
273 updated, merged, removed, unresolved = 0, 0, 0, 0 |
279 action.sort() |
274 action.sort() |
280 for a in action: |
275 for a in action: |
281 f, m = a[:2] |
276 f, m = a[:2] |
282 if f[0] == "/": |
277 if f[0] == "/": |
317 util.set_exec(repo.wjoin(f), flag) |
312 util.set_exec(repo.wjoin(f), flag) |
318 |
313 |
319 return updated, merged, removed, unresolved |
314 return updated, merged, removed, unresolved |
320 |
315 |
321 def recordupdates(repo, action, branchmerge, mctx): |
316 def recordupdates(repo, action, branchmerge, mctx): |
|
317 "record merge actions to the dirstate" |
|
318 |
322 for a in action: |
319 for a in action: |
323 f, m = a[:2] |
320 f, m = a[:2] |
324 if m == "r": # remove |
321 if m == "r": # remove |
325 if branchmerge: |
322 if branchmerge: |
326 repo.dirstate.update([f], 'r') |
323 repo.dirstate.update([f], 'r') |
355 else: |
352 else: |
356 repo.dirstate.copy(f2, fd) |
353 repo.dirstate.copy(f2, fd) |
357 |
354 |
358 def update(repo, node, branchmerge=False, force=False, partial=None, |
355 def update(repo, node, branchmerge=False, force=False, partial=None, |
359 wlock=None, show_stats=True, remind=True): |
356 wlock=None, show_stats=True, remind=True): |
|
357 """ |
|
358 Perform a merge between the working directory and the given node |
|
359 |
|
360 branchmerge = whether to merge between branches |
|
361 force = whether to force branch merging or file overwriting |
|
362 partial = a function to filter file lists (dirstate not updated) |
|
363 wlock = working dir lock, if already held |
|
364 show_stats = whether to report merge statistics |
|
365 remind = whether to remind about merge |
|
366 """ |
360 |
367 |
361 if not wlock: |
368 if not wlock: |
362 wlock = repo.wlock() |
369 wlock = repo.wlock() |
363 |
370 |
364 overwrite = force and not branchmerge |
371 overwrite = force and not branchmerge |