##// END OF EJS Templates
merge: add _checkunknowndirs function for detecting path conflicts...
Mark Thomas -
r34551:53e4bcab default
parent child Browse files
Show More
@@ -1,1839 +1,1867 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 of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import hashlib
11 import hashlib
12 import shutil
12 import shutil
13 import struct
13 import struct
14
14
15 from .i18n import _
15 from .i18n import _
16 from .node import (
16 from .node import (
17 addednodeid,
17 addednodeid,
18 bin,
18 bin,
19 hex,
19 hex,
20 modifiednodeid,
20 modifiednodeid,
21 nullhex,
21 nullhex,
22 nullid,
22 nullid,
23 nullrev,
23 nullrev,
24 )
24 )
25 from . import (
25 from . import (
26 copies,
26 copies,
27 error,
27 error,
28 filemerge,
28 filemerge,
29 match as matchmod,
29 match as matchmod,
30 obsutil,
30 obsutil,
31 pycompat,
31 pycompat,
32 scmutil,
32 scmutil,
33 subrepo,
33 subrepo,
34 util,
34 util,
35 worker,
35 worker,
36 )
36 )
37
37
38 _pack = struct.pack
38 _pack = struct.pack
39 _unpack = struct.unpack
39 _unpack = struct.unpack
40
40
41 def _droponode(data):
41 def _droponode(data):
42 # used for compatibility for v1
42 # used for compatibility for v1
43 bits = data.split('\0')
43 bits = data.split('\0')
44 bits = bits[:-2] + bits[-1:]
44 bits = bits[:-2] + bits[-1:]
45 return '\0'.join(bits)
45 return '\0'.join(bits)
46
46
47 class mergestate(object):
47 class mergestate(object):
48 '''track 3-way merge state of individual files
48 '''track 3-way merge state of individual files
49
49
50 The merge state is stored on disk when needed. Two files are used: one with
50 The merge state is stored on disk when needed. Two files are used: one with
51 an old format (version 1), and one with a new format (version 2). Version 2
51 an old format (version 1), and one with a new format (version 2). Version 2
52 stores a superset of the data in version 1, including new kinds of records
52 stores a superset of the data in version 1, including new kinds of records
53 in the future. For more about the new format, see the documentation for
53 in the future. For more about the new format, see the documentation for
54 `_readrecordsv2`.
54 `_readrecordsv2`.
55
55
56 Each record can contain arbitrary content, and has an associated type. This
56 Each record can contain arbitrary content, and has an associated type. This
57 `type` should be a letter. If `type` is uppercase, the record is mandatory:
57 `type` should be a letter. If `type` is uppercase, the record is mandatory:
58 versions of Mercurial that don't support it should abort. If `type` is
58 versions of Mercurial that don't support it should abort. If `type` is
59 lowercase, the record can be safely ignored.
59 lowercase, the record can be safely ignored.
60
60
61 Currently known records:
61 Currently known records:
62
62
63 L: the node of the "local" part of the merge (hexified version)
63 L: the node of the "local" part of the merge (hexified version)
64 O: the node of the "other" part of the merge (hexified version)
64 O: the node of the "other" part of the merge (hexified version)
65 F: a file to be merged entry
65 F: a file to be merged entry
66 C: a change/delete or delete/change conflict
66 C: a change/delete or delete/change conflict
67 D: a file that the external merge driver will merge internally
67 D: a file that the external merge driver will merge internally
68 (experimental)
68 (experimental)
69 P: a path conflict (file vs directory)
69 P: a path conflict (file vs directory)
70 m: the external merge driver defined for this merge plus its run state
70 m: the external merge driver defined for this merge plus its run state
71 (experimental)
71 (experimental)
72 f: a (filename, dictionary) tuple of optional values for a given file
72 f: a (filename, dictionary) tuple of optional values for a given file
73 X: unsupported mandatory record type (used in tests)
73 X: unsupported mandatory record type (used in tests)
74 x: unsupported advisory record type (used in tests)
74 x: unsupported advisory record type (used in tests)
75 l: the labels for the parts of the merge.
75 l: the labels for the parts of the merge.
76
76
77 Merge driver run states (experimental):
77 Merge driver run states (experimental):
78 u: driver-resolved files unmarked -- needs to be run next time we're about
78 u: driver-resolved files unmarked -- needs to be run next time we're about
79 to resolve or commit
79 to resolve or commit
80 m: driver-resolved files marked -- only needs to be run before commit
80 m: driver-resolved files marked -- only needs to be run before commit
81 s: success/skipped -- does not need to be run any more
81 s: success/skipped -- does not need to be run any more
82
82
83 Merge record states (stored in self._state, indexed by filename):
83 Merge record states (stored in self._state, indexed by filename):
84 u: unresolved conflict
84 u: unresolved conflict
85 r: resolved conflict
85 r: resolved conflict
86 pu: unresolved path conflict (file conflicts with directory)
86 pu: unresolved path conflict (file conflicts with directory)
87 pr: resolved path conflict
87 pr: resolved path conflict
88 d: driver-resolved conflict
88 d: driver-resolved conflict
89
89
90 The resolve command transitions between 'u' and 'r' for conflicts and
90 The resolve command transitions between 'u' and 'r' for conflicts and
91 'pu' and 'pr' for path conflicts.
91 'pu' and 'pr' for path conflicts.
92 '''
92 '''
93 statepathv1 = 'merge/state'
93 statepathv1 = 'merge/state'
94 statepathv2 = 'merge/state2'
94 statepathv2 = 'merge/state2'
95
95
96 @staticmethod
96 @staticmethod
97 def clean(repo, node=None, other=None, labels=None):
97 def clean(repo, node=None, other=None, labels=None):
98 """Initialize a brand new merge state, removing any existing state on
98 """Initialize a brand new merge state, removing any existing state on
99 disk."""
99 disk."""
100 ms = mergestate(repo)
100 ms = mergestate(repo)
101 ms.reset(node, other, labels)
101 ms.reset(node, other, labels)
102 return ms
102 return ms
103
103
104 @staticmethod
104 @staticmethod
105 def read(repo):
105 def read(repo):
106 """Initialize the merge state, reading it from disk."""
106 """Initialize the merge state, reading it from disk."""
107 ms = mergestate(repo)
107 ms = mergestate(repo)
108 ms._read()
108 ms._read()
109 return ms
109 return ms
110
110
111 def __init__(self, repo):
111 def __init__(self, repo):
112 """Initialize the merge state.
112 """Initialize the merge state.
113
113
114 Do not use this directly! Instead call read() or clean()."""
114 Do not use this directly! Instead call read() or clean()."""
115 self._repo = repo
115 self._repo = repo
116 self._dirty = False
116 self._dirty = False
117 self._labels = None
117 self._labels = None
118
118
119 def reset(self, node=None, other=None, labels=None):
119 def reset(self, node=None, other=None, labels=None):
120 self._state = {}
120 self._state = {}
121 self._stateextras = {}
121 self._stateextras = {}
122 self._local = None
122 self._local = None
123 self._other = None
123 self._other = None
124 self._labels = labels
124 self._labels = labels
125 for var in ('localctx', 'otherctx'):
125 for var in ('localctx', 'otherctx'):
126 if var in vars(self):
126 if var in vars(self):
127 delattr(self, var)
127 delattr(self, var)
128 if node:
128 if node:
129 self._local = node
129 self._local = node
130 self._other = other
130 self._other = other
131 self._readmergedriver = None
131 self._readmergedriver = None
132 if self.mergedriver:
132 if self.mergedriver:
133 self._mdstate = 's'
133 self._mdstate = 's'
134 else:
134 else:
135 self._mdstate = 'u'
135 self._mdstate = 'u'
136 shutil.rmtree(self._repo.vfs.join('merge'), True)
136 shutil.rmtree(self._repo.vfs.join('merge'), True)
137 self._results = {}
137 self._results = {}
138 self._dirty = False
138 self._dirty = False
139
139
140 def _read(self):
140 def _read(self):
141 """Analyse each record content to restore a serialized state from disk
141 """Analyse each record content to restore a serialized state from disk
142
142
143 This function process "record" entry produced by the de-serialization
143 This function process "record" entry produced by the de-serialization
144 of on disk file.
144 of on disk file.
145 """
145 """
146 self._state = {}
146 self._state = {}
147 self._stateextras = {}
147 self._stateextras = {}
148 self._local = None
148 self._local = None
149 self._other = None
149 self._other = None
150 for var in ('localctx', 'otherctx'):
150 for var in ('localctx', 'otherctx'):
151 if var in vars(self):
151 if var in vars(self):
152 delattr(self, var)
152 delattr(self, var)
153 self._readmergedriver = None
153 self._readmergedriver = None
154 self._mdstate = 's'
154 self._mdstate = 's'
155 unsupported = set()
155 unsupported = set()
156 records = self._readrecords()
156 records = self._readrecords()
157 for rtype, record in records:
157 for rtype, record in records:
158 if rtype == 'L':
158 if rtype == 'L':
159 self._local = bin(record)
159 self._local = bin(record)
160 elif rtype == 'O':
160 elif rtype == 'O':
161 self._other = bin(record)
161 self._other = bin(record)
162 elif rtype == 'm':
162 elif rtype == 'm':
163 bits = record.split('\0', 1)
163 bits = record.split('\0', 1)
164 mdstate = bits[1]
164 mdstate = bits[1]
165 if len(mdstate) != 1 or mdstate not in 'ums':
165 if len(mdstate) != 1 or mdstate not in 'ums':
166 # the merge driver should be idempotent, so just rerun it
166 # the merge driver should be idempotent, so just rerun it
167 mdstate = 'u'
167 mdstate = 'u'
168
168
169 self._readmergedriver = bits[0]
169 self._readmergedriver = bits[0]
170 self._mdstate = mdstate
170 self._mdstate = mdstate
171 elif rtype in 'FDCP':
171 elif rtype in 'FDCP':
172 bits = record.split('\0')
172 bits = record.split('\0')
173 self._state[bits[0]] = bits[1:]
173 self._state[bits[0]] = bits[1:]
174 elif rtype == 'f':
174 elif rtype == 'f':
175 filename, rawextras = record.split('\0', 1)
175 filename, rawextras = record.split('\0', 1)
176 extraparts = rawextras.split('\0')
176 extraparts = rawextras.split('\0')
177 extras = {}
177 extras = {}
178 i = 0
178 i = 0
179 while i < len(extraparts):
179 while i < len(extraparts):
180 extras[extraparts[i]] = extraparts[i + 1]
180 extras[extraparts[i]] = extraparts[i + 1]
181 i += 2
181 i += 2
182
182
183 self._stateextras[filename] = extras
183 self._stateextras[filename] = extras
184 elif rtype == 'l':
184 elif rtype == 'l':
185 labels = record.split('\0', 2)
185 labels = record.split('\0', 2)
186 self._labels = [l for l in labels if len(l) > 0]
186 self._labels = [l for l in labels if len(l) > 0]
187 elif not rtype.islower():
187 elif not rtype.islower():
188 unsupported.add(rtype)
188 unsupported.add(rtype)
189 self._results = {}
189 self._results = {}
190 self._dirty = False
190 self._dirty = False
191
191
192 if unsupported:
192 if unsupported:
193 raise error.UnsupportedMergeRecords(unsupported)
193 raise error.UnsupportedMergeRecords(unsupported)
194
194
195 def _readrecords(self):
195 def _readrecords(self):
196 """Read merge state from disk and return a list of record (TYPE, data)
196 """Read merge state from disk and return a list of record (TYPE, data)
197
197
198 We read data from both v1 and v2 files and decide which one to use.
198 We read data from both v1 and v2 files and decide which one to use.
199
199
200 V1 has been used by version prior to 2.9.1 and contains less data than
200 V1 has been used by version prior to 2.9.1 and contains less data than
201 v2. We read both versions and check if no data in v2 contradicts
201 v2. We read both versions and check if no data in v2 contradicts
202 v1. If there is not contradiction we can safely assume that both v1
202 v1. If there is not contradiction we can safely assume that both v1
203 and v2 were written at the same time and use the extract data in v2. If
203 and v2 were written at the same time and use the extract data in v2. If
204 there is contradiction we ignore v2 content as we assume an old version
204 there is contradiction we ignore v2 content as we assume an old version
205 of Mercurial has overwritten the mergestate file and left an old v2
205 of Mercurial has overwritten the mergestate file and left an old v2
206 file around.
206 file around.
207
207
208 returns list of record [(TYPE, data), ...]"""
208 returns list of record [(TYPE, data), ...]"""
209 v1records = self._readrecordsv1()
209 v1records = self._readrecordsv1()
210 v2records = self._readrecordsv2()
210 v2records = self._readrecordsv2()
211 if self._v1v2match(v1records, v2records):
211 if self._v1v2match(v1records, v2records):
212 return v2records
212 return v2records
213 else:
213 else:
214 # v1 file is newer than v2 file, use it
214 # v1 file is newer than v2 file, use it
215 # we have to infer the "other" changeset of the merge
215 # we have to infer the "other" changeset of the merge
216 # we cannot do better than that with v1 of the format
216 # we cannot do better than that with v1 of the format
217 mctx = self._repo[None].parents()[-1]
217 mctx = self._repo[None].parents()[-1]
218 v1records.append(('O', mctx.hex()))
218 v1records.append(('O', mctx.hex()))
219 # add place holder "other" file node information
219 # add place holder "other" file node information
220 # nobody is using it yet so we do no need to fetch the data
220 # nobody is using it yet so we do no need to fetch the data
221 # if mctx was wrong `mctx[bits[-2]]` may fails.
221 # if mctx was wrong `mctx[bits[-2]]` may fails.
222 for idx, r in enumerate(v1records):
222 for idx, r in enumerate(v1records):
223 if r[0] == 'F':
223 if r[0] == 'F':
224 bits = r[1].split('\0')
224 bits = r[1].split('\0')
225 bits.insert(-2, '')
225 bits.insert(-2, '')
226 v1records[idx] = (r[0], '\0'.join(bits))
226 v1records[idx] = (r[0], '\0'.join(bits))
227 return v1records
227 return v1records
228
228
229 def _v1v2match(self, v1records, v2records):
229 def _v1v2match(self, v1records, v2records):
230 oldv2 = set() # old format version of v2 record
230 oldv2 = set() # old format version of v2 record
231 for rec in v2records:
231 for rec in v2records:
232 if rec[0] == 'L':
232 if rec[0] == 'L':
233 oldv2.add(rec)
233 oldv2.add(rec)
234 elif rec[0] == 'F':
234 elif rec[0] == 'F':
235 # drop the onode data (not contained in v1)
235 # drop the onode data (not contained in v1)
236 oldv2.add(('F', _droponode(rec[1])))
236 oldv2.add(('F', _droponode(rec[1])))
237 for rec in v1records:
237 for rec in v1records:
238 if rec not in oldv2:
238 if rec not in oldv2:
239 return False
239 return False
240 else:
240 else:
241 return True
241 return True
242
242
243 def _readrecordsv1(self):
243 def _readrecordsv1(self):
244 """read on disk merge state for version 1 file
244 """read on disk merge state for version 1 file
245
245
246 returns list of record [(TYPE, data), ...]
246 returns list of record [(TYPE, data), ...]
247
247
248 Note: the "F" data from this file are one entry short
248 Note: the "F" data from this file are one entry short
249 (no "other file node" entry)
249 (no "other file node" entry)
250 """
250 """
251 records = []
251 records = []
252 try:
252 try:
253 f = self._repo.vfs(self.statepathv1)
253 f = self._repo.vfs(self.statepathv1)
254 for i, l in enumerate(f):
254 for i, l in enumerate(f):
255 if i == 0:
255 if i == 0:
256 records.append(('L', l[:-1]))
256 records.append(('L', l[:-1]))
257 else:
257 else:
258 records.append(('F', l[:-1]))
258 records.append(('F', l[:-1]))
259 f.close()
259 f.close()
260 except IOError as err:
260 except IOError as err:
261 if err.errno != errno.ENOENT:
261 if err.errno != errno.ENOENT:
262 raise
262 raise
263 return records
263 return records
264
264
265 def _readrecordsv2(self):
265 def _readrecordsv2(self):
266 """read on disk merge state for version 2 file
266 """read on disk merge state for version 2 file
267
267
268 This format is a list of arbitrary records of the form:
268 This format is a list of arbitrary records of the form:
269
269
270 [type][length][content]
270 [type][length][content]
271
271
272 `type` is a single character, `length` is a 4 byte integer, and
272 `type` is a single character, `length` is a 4 byte integer, and
273 `content` is an arbitrary byte sequence of length `length`.
273 `content` is an arbitrary byte sequence of length `length`.
274
274
275 Mercurial versions prior to 3.7 have a bug where if there are
275 Mercurial versions prior to 3.7 have a bug where if there are
276 unsupported mandatory merge records, attempting to clear out the merge
276 unsupported mandatory merge records, attempting to clear out the merge
277 state with hg update --clean or similar aborts. The 't' record type
277 state with hg update --clean or similar aborts. The 't' record type
278 works around that by writing out what those versions treat as an
278 works around that by writing out what those versions treat as an
279 advisory record, but later versions interpret as special: the first
279 advisory record, but later versions interpret as special: the first
280 character is the 'real' record type and everything onwards is the data.
280 character is the 'real' record type and everything onwards is the data.
281
281
282 Returns list of records [(TYPE, data), ...]."""
282 Returns list of records [(TYPE, data), ...]."""
283 records = []
283 records = []
284 try:
284 try:
285 f = self._repo.vfs(self.statepathv2)
285 f = self._repo.vfs(self.statepathv2)
286 data = f.read()
286 data = f.read()
287 off = 0
287 off = 0
288 end = len(data)
288 end = len(data)
289 while off < end:
289 while off < end:
290 rtype = data[off]
290 rtype = data[off]
291 off += 1
291 off += 1
292 length = _unpack('>I', data[off:(off + 4)])[0]
292 length = _unpack('>I', data[off:(off + 4)])[0]
293 off += 4
293 off += 4
294 record = data[off:(off + length)]
294 record = data[off:(off + length)]
295 off += length
295 off += length
296 if rtype == 't':
296 if rtype == 't':
297 rtype, record = record[0], record[1:]
297 rtype, record = record[0], record[1:]
298 records.append((rtype, record))
298 records.append((rtype, record))
299 f.close()
299 f.close()
300 except IOError as err:
300 except IOError as err:
301 if err.errno != errno.ENOENT:
301 if err.errno != errno.ENOENT:
302 raise
302 raise
303 return records
303 return records
304
304
305 @util.propertycache
305 @util.propertycache
306 def mergedriver(self):
306 def mergedriver(self):
307 # protect against the following:
307 # protect against the following:
308 # - A configures a malicious merge driver in their hgrc, then
308 # - A configures a malicious merge driver in their hgrc, then
309 # pauses the merge
309 # pauses the merge
310 # - A edits their hgrc to remove references to the merge driver
310 # - A edits their hgrc to remove references to the merge driver
311 # - A gives a copy of their entire repo, including .hg, to B
311 # - A gives a copy of their entire repo, including .hg, to B
312 # - B inspects .hgrc and finds it to be clean
312 # - B inspects .hgrc and finds it to be clean
313 # - B then continues the merge and the malicious merge driver
313 # - B then continues the merge and the malicious merge driver
314 # gets invoked
314 # gets invoked
315 configmergedriver = self._repo.ui.config('experimental', 'mergedriver')
315 configmergedriver = self._repo.ui.config('experimental', 'mergedriver')
316 if (self._readmergedriver is not None
316 if (self._readmergedriver is not None
317 and self._readmergedriver != configmergedriver):
317 and self._readmergedriver != configmergedriver):
318 raise error.ConfigError(
318 raise error.ConfigError(
319 _("merge driver changed since merge started"),
319 _("merge driver changed since merge started"),
320 hint=_("revert merge driver change or abort merge"))
320 hint=_("revert merge driver change or abort merge"))
321
321
322 return configmergedriver
322 return configmergedriver
323
323
324 @util.propertycache
324 @util.propertycache
325 def localctx(self):
325 def localctx(self):
326 if self._local is None:
326 if self._local is None:
327 msg = "localctx accessed but self._local isn't set"
327 msg = "localctx accessed but self._local isn't set"
328 raise error.ProgrammingError(msg)
328 raise error.ProgrammingError(msg)
329 return self._repo[self._local]
329 return self._repo[self._local]
330
330
331 @util.propertycache
331 @util.propertycache
332 def otherctx(self):
332 def otherctx(self):
333 if self._other is None:
333 if self._other is None:
334 msg = "otherctx accessed but self._other isn't set"
334 msg = "otherctx accessed but self._other isn't set"
335 raise error.ProgrammingError(msg)
335 raise error.ProgrammingError(msg)
336 return self._repo[self._other]
336 return self._repo[self._other]
337
337
338 def active(self):
338 def active(self):
339 """Whether mergestate is active.
339 """Whether mergestate is active.
340
340
341 Returns True if there appears to be mergestate. This is a rough proxy
341 Returns True if there appears to be mergestate. This is a rough proxy
342 for "is a merge in progress."
342 for "is a merge in progress."
343 """
343 """
344 # Check local variables before looking at filesystem for performance
344 # Check local variables before looking at filesystem for performance
345 # reasons.
345 # reasons.
346 return bool(self._local) or bool(self._state) or \
346 return bool(self._local) or bool(self._state) or \
347 self._repo.vfs.exists(self.statepathv1) or \
347 self._repo.vfs.exists(self.statepathv1) or \
348 self._repo.vfs.exists(self.statepathv2)
348 self._repo.vfs.exists(self.statepathv2)
349
349
350 def commit(self):
350 def commit(self):
351 """Write current state on disk (if necessary)"""
351 """Write current state on disk (if necessary)"""
352 if self._dirty:
352 if self._dirty:
353 records = self._makerecords()
353 records = self._makerecords()
354 self._writerecords(records)
354 self._writerecords(records)
355 self._dirty = False
355 self._dirty = False
356
356
357 def _makerecords(self):
357 def _makerecords(self):
358 records = []
358 records = []
359 records.append(('L', hex(self._local)))
359 records.append(('L', hex(self._local)))
360 records.append(('O', hex(self._other)))
360 records.append(('O', hex(self._other)))
361 if self.mergedriver:
361 if self.mergedriver:
362 records.append(('m', '\0'.join([
362 records.append(('m', '\0'.join([
363 self.mergedriver, self._mdstate])))
363 self.mergedriver, self._mdstate])))
364 for d, v in self._state.iteritems():
364 for d, v in self._state.iteritems():
365 if v[0] == 'd':
365 if v[0] == 'd':
366 records.append(('D', '\0'.join([d] + v)))
366 records.append(('D', '\0'.join([d] + v)))
367 elif v[0] in ('pu', 'pr'):
367 elif v[0] in ('pu', 'pr'):
368 records.append(('P', '\0'.join([d] + v)))
368 records.append(('P', '\0'.join([d] + v)))
369 # v[1] == local ('cd'), v[6] == other ('dc') -- not supported by
369 # v[1] == local ('cd'), v[6] == other ('dc') -- not supported by
370 # older versions of Mercurial
370 # older versions of Mercurial
371 elif v[1] == nullhex or v[6] == nullhex:
371 elif v[1] == nullhex or v[6] == nullhex:
372 records.append(('C', '\0'.join([d] + v)))
372 records.append(('C', '\0'.join([d] + v)))
373 else:
373 else:
374 records.append(('F', '\0'.join([d] + v)))
374 records.append(('F', '\0'.join([d] + v)))
375 for filename, extras in sorted(self._stateextras.iteritems()):
375 for filename, extras in sorted(self._stateextras.iteritems()):
376 rawextras = '\0'.join('%s\0%s' % (k, v) for k, v in
376 rawextras = '\0'.join('%s\0%s' % (k, v) for k, v in
377 extras.iteritems())
377 extras.iteritems())
378 records.append(('f', '%s\0%s' % (filename, rawextras)))
378 records.append(('f', '%s\0%s' % (filename, rawextras)))
379 if self._labels is not None:
379 if self._labels is not None:
380 labels = '\0'.join(self._labels)
380 labels = '\0'.join(self._labels)
381 records.append(('l', labels))
381 records.append(('l', labels))
382 return records
382 return records
383
383
384 def _writerecords(self, records):
384 def _writerecords(self, records):
385 """Write current state on disk (both v1 and v2)"""
385 """Write current state on disk (both v1 and v2)"""
386 self._writerecordsv1(records)
386 self._writerecordsv1(records)
387 self._writerecordsv2(records)
387 self._writerecordsv2(records)
388
388
389 def _writerecordsv1(self, records):
389 def _writerecordsv1(self, records):
390 """Write current state on disk in a version 1 file"""
390 """Write current state on disk in a version 1 file"""
391 f = self._repo.vfs(self.statepathv1, 'w')
391 f = self._repo.vfs(self.statepathv1, 'w')
392 irecords = iter(records)
392 irecords = iter(records)
393 lrecords = next(irecords)
393 lrecords = next(irecords)
394 assert lrecords[0] == 'L'
394 assert lrecords[0] == 'L'
395 f.write(hex(self._local) + '\n')
395 f.write(hex(self._local) + '\n')
396 for rtype, data in irecords:
396 for rtype, data in irecords:
397 if rtype == 'F':
397 if rtype == 'F':
398 f.write('%s\n' % _droponode(data))
398 f.write('%s\n' % _droponode(data))
399 f.close()
399 f.close()
400
400
401 def _writerecordsv2(self, records):
401 def _writerecordsv2(self, records):
402 """Write current state on disk in a version 2 file
402 """Write current state on disk in a version 2 file
403
403
404 See the docstring for _readrecordsv2 for why we use 't'."""
404 See the docstring for _readrecordsv2 for why we use 't'."""
405 # these are the records that all version 2 clients can read
405 # these are the records that all version 2 clients can read
406 whitelist = 'LOF'
406 whitelist = 'LOF'
407 f = self._repo.vfs(self.statepathv2, 'w')
407 f = self._repo.vfs(self.statepathv2, 'w')
408 for key, data in records:
408 for key, data in records:
409 assert len(key) == 1
409 assert len(key) == 1
410 if key not in whitelist:
410 if key not in whitelist:
411 key, data = 't', '%s%s' % (key, data)
411 key, data = 't', '%s%s' % (key, data)
412 format = '>sI%is' % len(data)
412 format = '>sI%is' % len(data)
413 f.write(_pack(format, key, len(data), data))
413 f.write(_pack(format, key, len(data), data))
414 f.close()
414 f.close()
415
415
416 def add(self, fcl, fco, fca, fd):
416 def add(self, fcl, fco, fca, fd):
417 """add a new (potentially?) conflicting file the merge state
417 """add a new (potentially?) conflicting file the merge state
418 fcl: file context for local,
418 fcl: file context for local,
419 fco: file context for remote,
419 fco: file context for remote,
420 fca: file context for ancestors,
420 fca: file context for ancestors,
421 fd: file path of the resulting merge.
421 fd: file path of the resulting merge.
422
422
423 note: also write the local version to the `.hg/merge` directory.
423 note: also write the local version to the `.hg/merge` directory.
424 """
424 """
425 if fcl.isabsent():
425 if fcl.isabsent():
426 hash = nullhex
426 hash = nullhex
427 else:
427 else:
428 hash = hex(hashlib.sha1(fcl.path()).digest())
428 hash = hex(hashlib.sha1(fcl.path()).digest())
429 self._repo.vfs.write('merge/' + hash, fcl.data())
429 self._repo.vfs.write('merge/' + hash, fcl.data())
430 self._state[fd] = ['u', hash, fcl.path(),
430 self._state[fd] = ['u', hash, fcl.path(),
431 fca.path(), hex(fca.filenode()),
431 fca.path(), hex(fca.filenode()),
432 fco.path(), hex(fco.filenode()),
432 fco.path(), hex(fco.filenode()),
433 fcl.flags()]
433 fcl.flags()]
434 self._stateextras[fd] = {'ancestorlinknode': hex(fca.node())}
434 self._stateextras[fd] = {'ancestorlinknode': hex(fca.node())}
435 self._dirty = True
435 self._dirty = True
436
436
437 def addpath(self, path, frename, forigin):
437 def addpath(self, path, frename, forigin):
438 """add a new conflicting path to the merge state
438 """add a new conflicting path to the merge state
439 path: the path that conflicts
439 path: the path that conflicts
440 frename: the filename the conflicting file was renamed to
440 frename: the filename the conflicting file was renamed to
441 forigin: origin of the file ('l' or 'r' for local/remote)
441 forigin: origin of the file ('l' or 'r' for local/remote)
442 """
442 """
443 self._state[path] = ['pu', frename, forigin]
443 self._state[path] = ['pu', frename, forigin]
444 self._dirty = True
444 self._dirty = True
445
445
446 def __contains__(self, dfile):
446 def __contains__(self, dfile):
447 return dfile in self._state
447 return dfile in self._state
448
448
449 def __getitem__(self, dfile):
449 def __getitem__(self, dfile):
450 return self._state[dfile][0]
450 return self._state[dfile][0]
451
451
452 def __iter__(self):
452 def __iter__(self):
453 return iter(sorted(self._state))
453 return iter(sorted(self._state))
454
454
455 def files(self):
455 def files(self):
456 return self._state.keys()
456 return self._state.keys()
457
457
458 def mark(self, dfile, state):
458 def mark(self, dfile, state):
459 self._state[dfile][0] = state
459 self._state[dfile][0] = state
460 self._dirty = True
460 self._dirty = True
461
461
462 def mdstate(self):
462 def mdstate(self):
463 return self._mdstate
463 return self._mdstate
464
464
465 def unresolved(self):
465 def unresolved(self):
466 """Obtain the paths of unresolved files."""
466 """Obtain the paths of unresolved files."""
467
467
468 for f, entry in self._state.iteritems():
468 for f, entry in self._state.iteritems():
469 if entry[0] in ('u', 'pu'):
469 if entry[0] in ('u', 'pu'):
470 yield f
470 yield f
471
471
472 def driverresolved(self):
472 def driverresolved(self):
473 """Obtain the paths of driver-resolved files."""
473 """Obtain the paths of driver-resolved files."""
474
474
475 for f, entry in self._state.items():
475 for f, entry in self._state.items():
476 if entry[0] == 'd':
476 if entry[0] == 'd':
477 yield f
477 yield f
478
478
479 def extras(self, filename):
479 def extras(self, filename):
480 return self._stateextras.setdefault(filename, {})
480 return self._stateextras.setdefault(filename, {})
481
481
482 def _resolve(self, preresolve, dfile, wctx):
482 def _resolve(self, preresolve, dfile, wctx):
483 """rerun merge process for file path `dfile`"""
483 """rerun merge process for file path `dfile`"""
484 if self[dfile] in 'rd':
484 if self[dfile] in 'rd':
485 return True, 0
485 return True, 0
486 stateentry = self._state[dfile]
486 stateentry = self._state[dfile]
487 state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
487 state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
488 octx = self._repo[self._other]
488 octx = self._repo[self._other]
489 extras = self.extras(dfile)
489 extras = self.extras(dfile)
490 anccommitnode = extras.get('ancestorlinknode')
490 anccommitnode = extras.get('ancestorlinknode')
491 if anccommitnode:
491 if anccommitnode:
492 actx = self._repo[anccommitnode]
492 actx = self._repo[anccommitnode]
493 else:
493 else:
494 actx = None
494 actx = None
495 fcd = self._filectxorabsent(hash, wctx, dfile)
495 fcd = self._filectxorabsent(hash, wctx, dfile)
496 fco = self._filectxorabsent(onode, octx, ofile)
496 fco = self._filectxorabsent(onode, octx, ofile)
497 # TODO: move this to filectxorabsent
497 # TODO: move this to filectxorabsent
498 fca = self._repo.filectx(afile, fileid=anode, changeid=actx)
498 fca = self._repo.filectx(afile, fileid=anode, changeid=actx)
499 # "premerge" x flags
499 # "premerge" x flags
500 flo = fco.flags()
500 flo = fco.flags()
501 fla = fca.flags()
501 fla = fca.flags()
502 if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
502 if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
503 if fca.node() == nullid and flags != flo:
503 if fca.node() == nullid and flags != flo:
504 if preresolve:
504 if preresolve:
505 self._repo.ui.warn(
505 self._repo.ui.warn(
506 _('warning: cannot merge flags for %s '
506 _('warning: cannot merge flags for %s '
507 'without common ancestor - keeping local flags\n')
507 'without common ancestor - keeping local flags\n')
508 % afile)
508 % afile)
509 elif flags == fla:
509 elif flags == fla:
510 flags = flo
510 flags = flo
511 if preresolve:
511 if preresolve:
512 # restore local
512 # restore local
513 if hash != nullhex:
513 if hash != nullhex:
514 f = self._repo.vfs('merge/' + hash)
514 f = self._repo.vfs('merge/' + hash)
515 wctx[dfile].write(f.read(), flags)
515 wctx[dfile].write(f.read(), flags)
516 f.close()
516 f.close()
517 else:
517 else:
518 wctx[dfile].remove(ignoremissing=True)
518 wctx[dfile].remove(ignoremissing=True)
519 complete, r, deleted = filemerge.premerge(self._repo, wctx,
519 complete, r, deleted = filemerge.premerge(self._repo, wctx,
520 self._local, lfile, fcd,
520 self._local, lfile, fcd,
521 fco, fca,
521 fco, fca,
522 labels=self._labels)
522 labels=self._labels)
523 else:
523 else:
524 complete, r, deleted = filemerge.filemerge(self._repo, wctx,
524 complete, r, deleted = filemerge.filemerge(self._repo, wctx,
525 self._local, lfile, fcd,
525 self._local, lfile, fcd,
526 fco, fca,
526 fco, fca,
527 labels=self._labels)
527 labels=self._labels)
528 if r is None:
528 if r is None:
529 # no real conflict
529 # no real conflict
530 del self._state[dfile]
530 del self._state[dfile]
531 self._stateextras.pop(dfile, None)
531 self._stateextras.pop(dfile, None)
532 self._dirty = True
532 self._dirty = True
533 elif not r:
533 elif not r:
534 self.mark(dfile, 'r')
534 self.mark(dfile, 'r')
535
535
536 if complete:
536 if complete:
537 action = None
537 action = None
538 if deleted:
538 if deleted:
539 if fcd.isabsent():
539 if fcd.isabsent():
540 # dc: local picked. Need to drop if present, which may
540 # dc: local picked. Need to drop if present, which may
541 # happen on re-resolves.
541 # happen on re-resolves.
542 action = 'f'
542 action = 'f'
543 else:
543 else:
544 # cd: remote picked (or otherwise deleted)
544 # cd: remote picked (or otherwise deleted)
545 action = 'r'
545 action = 'r'
546 else:
546 else:
547 if fcd.isabsent(): # dc: remote picked
547 if fcd.isabsent(): # dc: remote picked
548 action = 'g'
548 action = 'g'
549 elif fco.isabsent(): # cd: local picked
549 elif fco.isabsent(): # cd: local picked
550 if dfile in self.localctx:
550 if dfile in self.localctx:
551 action = 'am'
551 action = 'am'
552 else:
552 else:
553 action = 'a'
553 action = 'a'
554 # else: regular merges (no action necessary)
554 # else: regular merges (no action necessary)
555 self._results[dfile] = r, action
555 self._results[dfile] = r, action
556
556
557 return complete, r
557 return complete, r
558
558
559 def _filectxorabsent(self, hexnode, ctx, f):
559 def _filectxorabsent(self, hexnode, ctx, f):
560 if hexnode == nullhex:
560 if hexnode == nullhex:
561 return filemerge.absentfilectx(ctx, f)
561 return filemerge.absentfilectx(ctx, f)
562 else:
562 else:
563 return ctx[f]
563 return ctx[f]
564
564
565 def preresolve(self, dfile, wctx):
565 def preresolve(self, dfile, wctx):
566 """run premerge process for dfile
566 """run premerge process for dfile
567
567
568 Returns whether the merge is complete, and the exit code."""
568 Returns whether the merge is complete, and the exit code."""
569 return self._resolve(True, dfile, wctx)
569 return self._resolve(True, dfile, wctx)
570
570
571 def resolve(self, dfile, wctx):
571 def resolve(self, dfile, wctx):
572 """run merge process (assuming premerge was run) for dfile
572 """run merge process (assuming premerge was run) for dfile
573
573
574 Returns the exit code of the merge."""
574 Returns the exit code of the merge."""
575 return self._resolve(False, dfile, wctx)[1]
575 return self._resolve(False, dfile, wctx)[1]
576
576
577 def counts(self):
577 def counts(self):
578 """return counts for updated, merged and removed files in this
578 """return counts for updated, merged and removed files in this
579 session"""
579 session"""
580 updated, merged, removed = 0, 0, 0
580 updated, merged, removed = 0, 0, 0
581 for r, action in self._results.itervalues():
581 for r, action in self._results.itervalues():
582 if r is None:
582 if r is None:
583 updated += 1
583 updated += 1
584 elif r == 0:
584 elif r == 0:
585 if action == 'r':
585 if action == 'r':
586 removed += 1
586 removed += 1
587 else:
587 else:
588 merged += 1
588 merged += 1
589 return updated, merged, removed
589 return updated, merged, removed
590
590
591 def unresolvedcount(self):
591 def unresolvedcount(self):
592 """get unresolved count for this merge (persistent)"""
592 """get unresolved count for this merge (persistent)"""
593 return len(list(self.unresolved()))
593 return len(list(self.unresolved()))
594
594
595 def actions(self):
595 def actions(self):
596 """return lists of actions to perform on the dirstate"""
596 """return lists of actions to perform on the dirstate"""
597 actions = {'r': [], 'f': [], 'a': [], 'am': [], 'g': []}
597 actions = {'r': [], 'f': [], 'a': [], 'am': [], 'g': []}
598 for f, (r, action) in self._results.iteritems():
598 for f, (r, action) in self._results.iteritems():
599 if action is not None:
599 if action is not None:
600 actions[action].append((f, None, "merge result"))
600 actions[action].append((f, None, "merge result"))
601 return actions
601 return actions
602
602
603 def recordactions(self):
603 def recordactions(self):
604 """record remove/add/get actions in the dirstate"""
604 """record remove/add/get actions in the dirstate"""
605 branchmerge = self._repo.dirstate.p2() != nullid
605 branchmerge = self._repo.dirstate.p2() != nullid
606 recordupdates(self._repo, self.actions(), branchmerge)
606 recordupdates(self._repo, self.actions(), branchmerge)
607
607
608 def queueremove(self, f):
608 def queueremove(self, f):
609 """queues a file to be removed from the dirstate
609 """queues a file to be removed from the dirstate
610
610
611 Meant for use by custom merge drivers."""
611 Meant for use by custom merge drivers."""
612 self._results[f] = 0, 'r'
612 self._results[f] = 0, 'r'
613
613
614 def queueadd(self, f):
614 def queueadd(self, f):
615 """queues a file to be added to the dirstate
615 """queues a file to be added to the dirstate
616
616
617 Meant for use by custom merge drivers."""
617 Meant for use by custom merge drivers."""
618 self._results[f] = 0, 'a'
618 self._results[f] = 0, 'a'
619
619
620 def queueget(self, f):
620 def queueget(self, f):
621 """queues a file to be marked modified in the dirstate
621 """queues a file to be marked modified in the dirstate
622
622
623 Meant for use by custom merge drivers."""
623 Meant for use by custom merge drivers."""
624 self._results[f] = 0, 'g'
624 self._results[f] = 0, 'g'
625
625
626 def _getcheckunknownconfig(repo, section, name):
626 def _getcheckunknownconfig(repo, section, name):
627 config = repo.ui.config(section, name)
627 config = repo.ui.config(section, name)
628 valid = ['abort', 'ignore', 'warn']
628 valid = ['abort', 'ignore', 'warn']
629 if config not in valid:
629 if config not in valid:
630 validstr = ', '.join(["'" + v + "'" for v in valid])
630 validstr = ', '.join(["'" + v + "'" for v in valid])
631 raise error.ConfigError(_("%s.%s not valid "
631 raise error.ConfigError(_("%s.%s not valid "
632 "('%s' is none of %s)")
632 "('%s' is none of %s)")
633 % (section, name, config, validstr))
633 % (section, name, config, validstr))
634 return config
634 return config
635
635
636 def _checkunknownfile(repo, wctx, mctx, f, f2=None):
636 def _checkunknownfile(repo, wctx, mctx, f, f2=None):
637 if f2 is None:
637 if f2 is None:
638 f2 = f
638 f2 = f
639 return (repo.wvfs.audit.check(f)
639 return (repo.wvfs.audit.check(f)
640 and repo.wvfs.isfileorlink(f)
640 and repo.wvfs.isfileorlink(f)
641 and repo.dirstate.normalize(f) not in repo.dirstate
641 and repo.dirstate.normalize(f) not in repo.dirstate
642 and mctx[f2].cmp(wctx[f]))
642 and mctx[f2].cmp(wctx[f]))
643
643
644 def _checkunknowndirs(repo, f):
645 """
646 Look for any unknown files or directories that may have a path conflict
647 with a file. If any path prefix of the file exists as a file or link,
648 then it conflicts. If the file itself is a directory that contains any
649 file that is not tracked, then it conflicts.
650
651 Returns the shortest path at which a conflict occurs, or None if there is
652 no conflict.
653 """
654
655 # Check for path prefixes that exist as unknown files.
656 for p in reversed(list(util.finddirs(f))):
657 if (repo.wvfs.audit.check(p)
658 and repo.wvfs.isfileorlink(p)
659 and repo.dirstate.normalize(p) not in repo.dirstate):
660 return p
661
662 # Check if the file conflicts with a directory containing unknown files.
663 if repo.wvfs.audit.check(f) and repo.wvfs.isdir(f):
664 # Does the directory contain any files that are not in the dirstate?
665 for p, dirs, files in repo.wvfs.walk(f):
666 for fn in files:
667 relf = repo.dirstate.normalize(repo.wvfs.reljoin(p, fn))
668 if relf not in repo.dirstate:
669 return f
670 return None
671
644 def _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce):
672 def _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce):
645 """
673 """
646 Considers any actions that care about the presence of conflicting unknown
674 Considers any actions that care about the presence of conflicting unknown
647 files. For some actions, the result is to abort; for others, it is to
675 files. For some actions, the result is to abort; for others, it is to
648 choose a different action.
676 choose a different action.
649 """
677 """
650 conflicts = set()
678 conflicts = set()
651 warnconflicts = set()
679 warnconflicts = set()
652 abortconflicts = set()
680 abortconflicts = set()
653 unknownconfig = _getcheckunknownconfig(repo, 'merge', 'checkunknown')
681 unknownconfig = _getcheckunknownconfig(repo, 'merge', 'checkunknown')
654 ignoredconfig = _getcheckunknownconfig(repo, 'merge', 'checkignored')
682 ignoredconfig = _getcheckunknownconfig(repo, 'merge', 'checkignored')
655 if not force:
683 if not force:
656 def collectconflicts(conflicts, config):
684 def collectconflicts(conflicts, config):
657 if config == 'abort':
685 if config == 'abort':
658 abortconflicts.update(conflicts)
686 abortconflicts.update(conflicts)
659 elif config == 'warn':
687 elif config == 'warn':
660 warnconflicts.update(conflicts)
688 warnconflicts.update(conflicts)
661
689
662 for f, (m, args, msg) in actions.iteritems():
690 for f, (m, args, msg) in actions.iteritems():
663 if m in ('c', 'dc'):
691 if m in ('c', 'dc'):
664 if _checkunknownfile(repo, wctx, mctx, f):
692 if _checkunknownfile(repo, wctx, mctx, f):
665 conflicts.add(f)
693 conflicts.add(f)
666 elif m == 'dg':
694 elif m == 'dg':
667 if _checkunknownfile(repo, wctx, mctx, f, args[0]):
695 if _checkunknownfile(repo, wctx, mctx, f, args[0]):
668 conflicts.add(f)
696 conflicts.add(f)
669
697
670 ignoredconflicts = set([c for c in conflicts
698 ignoredconflicts = set([c for c in conflicts
671 if repo.dirstate._ignore(c)])
699 if repo.dirstate._ignore(c)])
672 unknownconflicts = conflicts - ignoredconflicts
700 unknownconflicts = conflicts - ignoredconflicts
673 collectconflicts(ignoredconflicts, ignoredconfig)
701 collectconflicts(ignoredconflicts, ignoredconfig)
674 collectconflicts(unknownconflicts, unknownconfig)
702 collectconflicts(unknownconflicts, unknownconfig)
675 else:
703 else:
676 for f, (m, args, msg) in actions.iteritems():
704 for f, (m, args, msg) in actions.iteritems():
677 if m == 'cm':
705 if m == 'cm':
678 fl2, anc = args
706 fl2, anc = args
679 different = _checkunknownfile(repo, wctx, mctx, f)
707 different = _checkunknownfile(repo, wctx, mctx, f)
680 if repo.dirstate._ignore(f):
708 if repo.dirstate._ignore(f):
681 config = ignoredconfig
709 config = ignoredconfig
682 else:
710 else:
683 config = unknownconfig
711 config = unknownconfig
684
712
685 # The behavior when force is True is described by this table:
713 # The behavior when force is True is described by this table:
686 # config different mergeforce | action backup
714 # config different mergeforce | action backup
687 # * n * | get n
715 # * n * | get n
688 # * y y | merge -
716 # * y y | merge -
689 # abort y n | merge - (1)
717 # abort y n | merge - (1)
690 # warn y n | warn + get y
718 # warn y n | warn + get y
691 # ignore y n | get y
719 # ignore y n | get y
692 #
720 #
693 # (1) this is probably the wrong behavior here -- we should
721 # (1) this is probably the wrong behavior here -- we should
694 # probably abort, but some actions like rebases currently
722 # probably abort, but some actions like rebases currently
695 # don't like an abort happening in the middle of
723 # don't like an abort happening in the middle of
696 # merge.update.
724 # merge.update.
697 if not different:
725 if not different:
698 actions[f] = ('g', (fl2, False), "remote created")
726 actions[f] = ('g', (fl2, False), "remote created")
699 elif mergeforce or config == 'abort':
727 elif mergeforce or config == 'abort':
700 actions[f] = ('m', (f, f, None, False, anc),
728 actions[f] = ('m', (f, f, None, False, anc),
701 "remote differs from untracked local")
729 "remote differs from untracked local")
702 elif config == 'abort':
730 elif config == 'abort':
703 abortconflicts.add(f)
731 abortconflicts.add(f)
704 else:
732 else:
705 if config == 'warn':
733 if config == 'warn':
706 warnconflicts.add(f)
734 warnconflicts.add(f)
707 actions[f] = ('g', (fl2, True), "remote created")
735 actions[f] = ('g', (fl2, True), "remote created")
708
736
709 for f in sorted(abortconflicts):
737 for f in sorted(abortconflicts):
710 repo.ui.warn(_("%s: untracked file differs\n") % f)
738 repo.ui.warn(_("%s: untracked file differs\n") % f)
711 if abortconflicts:
739 if abortconflicts:
712 raise error.Abort(_("untracked files in working directory "
740 raise error.Abort(_("untracked files in working directory "
713 "differ from files in requested revision"))
741 "differ from files in requested revision"))
714
742
715 for f in sorted(warnconflicts):
743 for f in sorted(warnconflicts):
716 repo.ui.warn(_("%s: replacing untracked file\n") % f)
744 repo.ui.warn(_("%s: replacing untracked file\n") % f)
717
745
718 for f, (m, args, msg) in actions.iteritems():
746 for f, (m, args, msg) in actions.iteritems():
719 backup = f in conflicts
747 backup = f in conflicts
720 if m == 'c':
748 if m == 'c':
721 flags, = args
749 flags, = args
722 actions[f] = ('g', (flags, backup), msg)
750 actions[f] = ('g', (flags, backup), msg)
723
751
724 def _forgetremoved(wctx, mctx, branchmerge):
752 def _forgetremoved(wctx, mctx, branchmerge):
725 """
753 """
726 Forget removed files
754 Forget removed files
727
755
728 If we're jumping between revisions (as opposed to merging), and if
756 If we're jumping between revisions (as opposed to merging), and if
729 neither the working directory nor the target rev has the file,
757 neither the working directory nor the target rev has the file,
730 then we need to remove it from the dirstate, to prevent the
758 then we need to remove it from the dirstate, to prevent the
731 dirstate from listing the file when it is no longer in the
759 dirstate from listing the file when it is no longer in the
732 manifest.
760 manifest.
733
761
734 If we're merging, and the other revision has removed a file
762 If we're merging, and the other revision has removed a file
735 that is not present in the working directory, we need to mark it
763 that is not present in the working directory, we need to mark it
736 as removed.
764 as removed.
737 """
765 """
738
766
739 actions = {}
767 actions = {}
740 m = 'f'
768 m = 'f'
741 if branchmerge:
769 if branchmerge:
742 m = 'r'
770 m = 'r'
743 for f in wctx.deleted():
771 for f in wctx.deleted():
744 if f not in mctx:
772 if f not in mctx:
745 actions[f] = m, None, "forget deleted"
773 actions[f] = m, None, "forget deleted"
746
774
747 if not branchmerge:
775 if not branchmerge:
748 for f in wctx.removed():
776 for f in wctx.removed():
749 if f not in mctx:
777 if f not in mctx:
750 actions[f] = 'f', None, "forget removed"
778 actions[f] = 'f', None, "forget removed"
751
779
752 return actions
780 return actions
753
781
754 def _checkcollision(repo, wmf, actions):
782 def _checkcollision(repo, wmf, actions):
755 # build provisional merged manifest up
783 # build provisional merged manifest up
756 pmmf = set(wmf)
784 pmmf = set(wmf)
757
785
758 if actions:
786 if actions:
759 # k, dr, e and rd are no-op
787 # k, dr, e and rd are no-op
760 for m in 'a', 'am', 'f', 'g', 'cd', 'dc':
788 for m in 'a', 'am', 'f', 'g', 'cd', 'dc':
761 for f, args, msg in actions[m]:
789 for f, args, msg in actions[m]:
762 pmmf.add(f)
790 pmmf.add(f)
763 for f, args, msg in actions['r']:
791 for f, args, msg in actions['r']:
764 pmmf.discard(f)
792 pmmf.discard(f)
765 for f, args, msg in actions['dm']:
793 for f, args, msg in actions['dm']:
766 f2, flags = args
794 f2, flags = args
767 pmmf.discard(f2)
795 pmmf.discard(f2)
768 pmmf.add(f)
796 pmmf.add(f)
769 for f, args, msg in actions['dg']:
797 for f, args, msg in actions['dg']:
770 pmmf.add(f)
798 pmmf.add(f)
771 for f, args, msg in actions['m']:
799 for f, args, msg in actions['m']:
772 f1, f2, fa, move, anc = args
800 f1, f2, fa, move, anc = args
773 if move:
801 if move:
774 pmmf.discard(f1)
802 pmmf.discard(f1)
775 pmmf.add(f)
803 pmmf.add(f)
776
804
777 # check case-folding collision in provisional merged manifest
805 # check case-folding collision in provisional merged manifest
778 foldmap = {}
806 foldmap = {}
779 for f in pmmf:
807 for f in pmmf:
780 fold = util.normcase(f)
808 fold = util.normcase(f)
781 if fold in foldmap:
809 if fold in foldmap:
782 raise error.Abort(_("case-folding collision between %s and %s")
810 raise error.Abort(_("case-folding collision between %s and %s")
783 % (f, foldmap[fold]))
811 % (f, foldmap[fold]))
784 foldmap[fold] = f
812 foldmap[fold] = f
785
813
786 # check case-folding of directories
814 # check case-folding of directories
787 foldprefix = unfoldprefix = lastfull = ''
815 foldprefix = unfoldprefix = lastfull = ''
788 for fold, f in sorted(foldmap.items()):
816 for fold, f in sorted(foldmap.items()):
789 if fold.startswith(foldprefix) and not f.startswith(unfoldprefix):
817 if fold.startswith(foldprefix) and not f.startswith(unfoldprefix):
790 # the folded prefix matches but actual casing is different
818 # the folded prefix matches but actual casing is different
791 raise error.Abort(_("case-folding collision between "
819 raise error.Abort(_("case-folding collision between "
792 "%s and directory of %s") % (lastfull, f))
820 "%s and directory of %s") % (lastfull, f))
793 foldprefix = fold + '/'
821 foldprefix = fold + '/'
794 unfoldprefix = f + '/'
822 unfoldprefix = f + '/'
795 lastfull = f
823 lastfull = f
796
824
797 def driverpreprocess(repo, ms, wctx, labels=None):
825 def driverpreprocess(repo, ms, wctx, labels=None):
798 """run the preprocess step of the merge driver, if any
826 """run the preprocess step of the merge driver, if any
799
827
800 This is currently not implemented -- it's an extension point."""
828 This is currently not implemented -- it's an extension point."""
801 return True
829 return True
802
830
803 def driverconclude(repo, ms, wctx, labels=None):
831 def driverconclude(repo, ms, wctx, labels=None):
804 """run the conclude step of the merge driver, if any
832 """run the conclude step of the merge driver, if any
805
833
806 This is currently not implemented -- it's an extension point."""
834 This is currently not implemented -- it's an extension point."""
807 return True
835 return True
808
836
809 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, matcher,
837 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, matcher,
810 acceptremote, followcopies, forcefulldiff=False):
838 acceptremote, followcopies, forcefulldiff=False):
811 """
839 """
812 Merge wctx and p2 with ancestor pa and generate merge action list
840 Merge wctx and p2 with ancestor pa and generate merge action list
813
841
814 branchmerge and force are as passed in to update
842 branchmerge and force are as passed in to update
815 matcher = matcher to filter file lists
843 matcher = matcher to filter file lists
816 acceptremote = accept the incoming changes without prompting
844 acceptremote = accept the incoming changes without prompting
817 """
845 """
818 if matcher is not None and matcher.always():
846 if matcher is not None and matcher.always():
819 matcher = None
847 matcher = None
820
848
821 copy, movewithdir, diverge, renamedelete, dirmove = {}, {}, {}, {}, {}
849 copy, movewithdir, diverge, renamedelete, dirmove = {}, {}, {}, {}, {}
822
850
823 # manifests fetched in order are going to be faster, so prime the caches
851 # manifests fetched in order are going to be faster, so prime the caches
824 [x.manifest() for x in
852 [x.manifest() for x in
825 sorted(wctx.parents() + [p2, pa], key=scmutil.intrev)]
853 sorted(wctx.parents() + [p2, pa], key=scmutil.intrev)]
826
854
827 if followcopies:
855 if followcopies:
828 ret = copies.mergecopies(repo, wctx, p2, pa)
856 ret = copies.mergecopies(repo, wctx, p2, pa)
829 copy, movewithdir, diverge, renamedelete, dirmove = ret
857 copy, movewithdir, diverge, renamedelete, dirmove = ret
830
858
831 boolbm = pycompat.bytestr(bool(branchmerge))
859 boolbm = pycompat.bytestr(bool(branchmerge))
832 boolf = pycompat.bytestr(bool(force))
860 boolf = pycompat.bytestr(bool(force))
833 boolm = pycompat.bytestr(bool(matcher))
861 boolm = pycompat.bytestr(bool(matcher))
834 repo.ui.note(_("resolving manifests\n"))
862 repo.ui.note(_("resolving manifests\n"))
835 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
863 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
836 % (boolbm, boolf, boolm))
864 % (boolbm, boolf, boolm))
837 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
865 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
838
866
839 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
867 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
840 copied = set(copy.values())
868 copied = set(copy.values())
841 copied.update(movewithdir.values())
869 copied.update(movewithdir.values())
842
870
843 if '.hgsubstate' in m1:
871 if '.hgsubstate' in m1:
844 # check whether sub state is modified
872 # check whether sub state is modified
845 if any(wctx.sub(s).dirty() for s in wctx.substate):
873 if any(wctx.sub(s).dirty() for s in wctx.substate):
846 m1['.hgsubstate'] = modifiednodeid
874 m1['.hgsubstate'] = modifiednodeid
847
875
848 # Don't use m2-vs-ma optimization if:
876 # Don't use m2-vs-ma optimization if:
849 # - ma is the same as m1 or m2, which we're just going to diff again later
877 # - ma is the same as m1 or m2, which we're just going to diff again later
850 # - The caller specifically asks for a full diff, which is useful during bid
878 # - The caller specifically asks for a full diff, which is useful during bid
851 # merge.
879 # merge.
852 if (pa not in ([wctx, p2] + wctx.parents()) and not forcefulldiff):
880 if (pa not in ([wctx, p2] + wctx.parents()) and not forcefulldiff):
853 # Identify which files are relevant to the merge, so we can limit the
881 # Identify which files are relevant to the merge, so we can limit the
854 # total m1-vs-m2 diff to just those files. This has significant
882 # total m1-vs-m2 diff to just those files. This has significant
855 # performance benefits in large repositories.
883 # performance benefits in large repositories.
856 relevantfiles = set(ma.diff(m2).keys())
884 relevantfiles = set(ma.diff(m2).keys())
857
885
858 # For copied and moved files, we need to add the source file too.
886 # For copied and moved files, we need to add the source file too.
859 for copykey, copyvalue in copy.iteritems():
887 for copykey, copyvalue in copy.iteritems():
860 if copyvalue in relevantfiles:
888 if copyvalue in relevantfiles:
861 relevantfiles.add(copykey)
889 relevantfiles.add(copykey)
862 for movedirkey in movewithdir:
890 for movedirkey in movewithdir:
863 relevantfiles.add(movedirkey)
891 relevantfiles.add(movedirkey)
864 filesmatcher = scmutil.matchfiles(repo, relevantfiles)
892 filesmatcher = scmutil.matchfiles(repo, relevantfiles)
865 matcher = matchmod.intersectmatchers(matcher, filesmatcher)
893 matcher = matchmod.intersectmatchers(matcher, filesmatcher)
866
894
867 diff = m1.diff(m2, match=matcher)
895 diff = m1.diff(m2, match=matcher)
868
896
869 if matcher is None:
897 if matcher is None:
870 matcher = matchmod.always('', '')
898 matcher = matchmod.always('', '')
871
899
872 actions = {}
900 actions = {}
873 for f, ((n1, fl1), (n2, fl2)) in diff.iteritems():
901 for f, ((n1, fl1), (n2, fl2)) in diff.iteritems():
874 if n1 and n2: # file exists on both local and remote side
902 if n1 and n2: # file exists on both local and remote side
875 if f not in ma:
903 if f not in ma:
876 fa = copy.get(f, None)
904 fa = copy.get(f, None)
877 if fa is not None:
905 if fa is not None:
878 actions[f] = ('m', (f, f, fa, False, pa.node()),
906 actions[f] = ('m', (f, f, fa, False, pa.node()),
879 "both renamed from " + fa)
907 "both renamed from " + fa)
880 else:
908 else:
881 actions[f] = ('m', (f, f, None, False, pa.node()),
909 actions[f] = ('m', (f, f, None, False, pa.node()),
882 "both created")
910 "both created")
883 else:
911 else:
884 a = ma[f]
912 a = ma[f]
885 fla = ma.flags(f)
913 fla = ma.flags(f)
886 nol = 'l' not in fl1 + fl2 + fla
914 nol = 'l' not in fl1 + fl2 + fla
887 if n2 == a and fl2 == fla:
915 if n2 == a and fl2 == fla:
888 actions[f] = ('k', (), "remote unchanged")
916 actions[f] = ('k', (), "remote unchanged")
889 elif n1 == a and fl1 == fla: # local unchanged - use remote
917 elif n1 == a and fl1 == fla: # local unchanged - use remote
890 if n1 == n2: # optimization: keep local content
918 if n1 == n2: # optimization: keep local content
891 actions[f] = ('e', (fl2,), "update permissions")
919 actions[f] = ('e', (fl2,), "update permissions")
892 else:
920 else:
893 actions[f] = ('g', (fl2, False), "remote is newer")
921 actions[f] = ('g', (fl2, False), "remote is newer")
894 elif nol and n2 == a: # remote only changed 'x'
922 elif nol and n2 == a: # remote only changed 'x'
895 actions[f] = ('e', (fl2,), "update permissions")
923 actions[f] = ('e', (fl2,), "update permissions")
896 elif nol and n1 == a: # local only changed 'x'
924 elif nol and n1 == a: # local only changed 'x'
897 actions[f] = ('g', (fl1, False), "remote is newer")
925 actions[f] = ('g', (fl1, False), "remote is newer")
898 else: # both changed something
926 else: # both changed something
899 actions[f] = ('m', (f, f, f, False, pa.node()),
927 actions[f] = ('m', (f, f, f, False, pa.node()),
900 "versions differ")
928 "versions differ")
901 elif n1: # file exists only on local side
929 elif n1: # file exists only on local side
902 if f in copied:
930 if f in copied:
903 pass # we'll deal with it on m2 side
931 pass # we'll deal with it on m2 side
904 elif f in movewithdir: # directory rename, move local
932 elif f in movewithdir: # directory rename, move local
905 f2 = movewithdir[f]
933 f2 = movewithdir[f]
906 if f2 in m2:
934 if f2 in m2:
907 actions[f2] = ('m', (f, f2, None, True, pa.node()),
935 actions[f2] = ('m', (f, f2, None, True, pa.node()),
908 "remote directory rename, both created")
936 "remote directory rename, both created")
909 else:
937 else:
910 actions[f2] = ('dm', (f, fl1),
938 actions[f2] = ('dm', (f, fl1),
911 "remote directory rename - move from " + f)
939 "remote directory rename - move from " + f)
912 elif f in copy:
940 elif f in copy:
913 f2 = copy[f]
941 f2 = copy[f]
914 actions[f] = ('m', (f, f2, f2, False, pa.node()),
942 actions[f] = ('m', (f, f2, f2, False, pa.node()),
915 "local copied/moved from " + f2)
943 "local copied/moved from " + f2)
916 elif f in ma: # clean, a different, no remote
944 elif f in ma: # clean, a different, no remote
917 if n1 != ma[f]:
945 if n1 != ma[f]:
918 if acceptremote:
946 if acceptremote:
919 actions[f] = ('r', None, "remote delete")
947 actions[f] = ('r', None, "remote delete")
920 else:
948 else:
921 actions[f] = ('cd', (f, None, f, False, pa.node()),
949 actions[f] = ('cd', (f, None, f, False, pa.node()),
922 "prompt changed/deleted")
950 "prompt changed/deleted")
923 elif n1 == addednodeid:
951 elif n1 == addednodeid:
924 # This extra 'a' is added by working copy manifest to mark
952 # This extra 'a' is added by working copy manifest to mark
925 # the file as locally added. We should forget it instead of
953 # the file as locally added. We should forget it instead of
926 # deleting it.
954 # deleting it.
927 actions[f] = ('f', None, "remote deleted")
955 actions[f] = ('f', None, "remote deleted")
928 else:
956 else:
929 actions[f] = ('r', None, "other deleted")
957 actions[f] = ('r', None, "other deleted")
930 elif n2: # file exists only on remote side
958 elif n2: # file exists only on remote side
931 if f in copied:
959 if f in copied:
932 pass # we'll deal with it on m1 side
960 pass # we'll deal with it on m1 side
933 elif f in movewithdir:
961 elif f in movewithdir:
934 f2 = movewithdir[f]
962 f2 = movewithdir[f]
935 if f2 in m1:
963 if f2 in m1:
936 actions[f2] = ('m', (f2, f, None, False, pa.node()),
964 actions[f2] = ('m', (f2, f, None, False, pa.node()),
937 "local directory rename, both created")
965 "local directory rename, both created")
938 else:
966 else:
939 actions[f2] = ('dg', (f, fl2),
967 actions[f2] = ('dg', (f, fl2),
940 "local directory rename - get from " + f)
968 "local directory rename - get from " + f)
941 elif f in copy:
969 elif f in copy:
942 f2 = copy[f]
970 f2 = copy[f]
943 if f2 in m2:
971 if f2 in m2:
944 actions[f] = ('m', (f2, f, f2, False, pa.node()),
972 actions[f] = ('m', (f2, f, f2, False, pa.node()),
945 "remote copied from " + f2)
973 "remote copied from " + f2)
946 else:
974 else:
947 actions[f] = ('m', (f2, f, f2, True, pa.node()),
975 actions[f] = ('m', (f2, f, f2, True, pa.node()),
948 "remote moved from " + f2)
976 "remote moved from " + f2)
949 elif f not in ma:
977 elif f not in ma:
950 # local unknown, remote created: the logic is described by the
978 # local unknown, remote created: the logic is described by the
951 # following table:
979 # following table:
952 #
980 #
953 # force branchmerge different | action
981 # force branchmerge different | action
954 # n * * | create
982 # n * * | create
955 # y n * | create
983 # y n * | create
956 # y y n | create
984 # y y n | create
957 # y y y | merge
985 # y y y | merge
958 #
986 #
959 # Checking whether the files are different is expensive, so we
987 # Checking whether the files are different is expensive, so we
960 # don't do that when we can avoid it.
988 # don't do that when we can avoid it.
961 if not force:
989 if not force:
962 actions[f] = ('c', (fl2,), "remote created")
990 actions[f] = ('c', (fl2,), "remote created")
963 elif not branchmerge:
991 elif not branchmerge:
964 actions[f] = ('c', (fl2,), "remote created")
992 actions[f] = ('c', (fl2,), "remote created")
965 else:
993 else:
966 actions[f] = ('cm', (fl2, pa.node()),
994 actions[f] = ('cm', (fl2, pa.node()),
967 "remote created, get or merge")
995 "remote created, get or merge")
968 elif n2 != ma[f]:
996 elif n2 != ma[f]:
969 df = None
997 df = None
970 for d in dirmove:
998 for d in dirmove:
971 if f.startswith(d):
999 if f.startswith(d):
972 # new file added in a directory that was moved
1000 # new file added in a directory that was moved
973 df = dirmove[d] + f[len(d):]
1001 df = dirmove[d] + f[len(d):]
974 break
1002 break
975 if df is not None and df in m1:
1003 if df is not None and df in m1:
976 actions[df] = ('m', (df, f, f, False, pa.node()),
1004 actions[df] = ('m', (df, f, f, False, pa.node()),
977 "local directory rename - respect move from " + f)
1005 "local directory rename - respect move from " + f)
978 elif acceptremote:
1006 elif acceptremote:
979 actions[f] = ('c', (fl2,), "remote recreating")
1007 actions[f] = ('c', (fl2,), "remote recreating")
980 else:
1008 else:
981 actions[f] = ('dc', (None, f, f, False, pa.node()),
1009 actions[f] = ('dc', (None, f, f, False, pa.node()),
982 "prompt deleted/changed")
1010 "prompt deleted/changed")
983
1011
984 return actions, diverge, renamedelete
1012 return actions, diverge, renamedelete
985
1013
986 def _resolvetrivial(repo, wctx, mctx, ancestor, actions):
1014 def _resolvetrivial(repo, wctx, mctx, ancestor, actions):
987 """Resolves false conflicts where the nodeid changed but the content
1015 """Resolves false conflicts where the nodeid changed but the content
988 remained the same."""
1016 remained the same."""
989
1017
990 for f, (m, args, msg) in actions.items():
1018 for f, (m, args, msg) in actions.items():
991 if m == 'cd' and f in ancestor and not wctx[f].cmp(ancestor[f]):
1019 if m == 'cd' and f in ancestor and not wctx[f].cmp(ancestor[f]):
992 # local did change but ended up with same content
1020 # local did change but ended up with same content
993 actions[f] = 'r', None, "prompt same"
1021 actions[f] = 'r', None, "prompt same"
994 elif m == 'dc' and f in ancestor and not mctx[f].cmp(ancestor[f]):
1022 elif m == 'dc' and f in ancestor and not mctx[f].cmp(ancestor[f]):
995 # remote did change but ended up with same content
1023 # remote did change but ended up with same content
996 del actions[f] # don't get = keep local deleted
1024 del actions[f] # don't get = keep local deleted
997
1025
998 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force,
1026 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force,
999 acceptremote, followcopies, matcher=None,
1027 acceptremote, followcopies, matcher=None,
1000 mergeforce=False):
1028 mergeforce=False):
1001 """Calculate the actions needed to merge mctx into wctx using ancestors"""
1029 """Calculate the actions needed to merge mctx into wctx using ancestors"""
1002 # Avoid cycle.
1030 # Avoid cycle.
1003 from . import sparse
1031 from . import sparse
1004
1032
1005 if len(ancestors) == 1: # default
1033 if len(ancestors) == 1: # default
1006 actions, diverge, renamedelete = manifestmerge(
1034 actions, diverge, renamedelete = manifestmerge(
1007 repo, wctx, mctx, ancestors[0], branchmerge, force, matcher,
1035 repo, wctx, mctx, ancestors[0], branchmerge, force, matcher,
1008 acceptremote, followcopies)
1036 acceptremote, followcopies)
1009 _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce)
1037 _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce)
1010
1038
1011 else: # only when merge.preferancestor=* - the default
1039 else: # only when merge.preferancestor=* - the default
1012 repo.ui.note(
1040 repo.ui.note(
1013 _("note: merging %s and %s using bids from ancestors %s\n") %
1041 _("note: merging %s and %s using bids from ancestors %s\n") %
1014 (wctx, mctx, _(' and ').join(pycompat.bytestr(anc)
1042 (wctx, mctx, _(' and ').join(pycompat.bytestr(anc)
1015 for anc in ancestors)))
1043 for anc in ancestors)))
1016
1044
1017 # Call for bids
1045 # Call for bids
1018 fbids = {} # mapping filename to bids (action method to list af actions)
1046 fbids = {} # mapping filename to bids (action method to list af actions)
1019 diverge, renamedelete = None, None
1047 diverge, renamedelete = None, None
1020 for ancestor in ancestors:
1048 for ancestor in ancestors:
1021 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
1049 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
1022 actions, diverge1, renamedelete1 = manifestmerge(
1050 actions, diverge1, renamedelete1 = manifestmerge(
1023 repo, wctx, mctx, ancestor, branchmerge, force, matcher,
1051 repo, wctx, mctx, ancestor, branchmerge, force, matcher,
1024 acceptremote, followcopies, forcefulldiff=True)
1052 acceptremote, followcopies, forcefulldiff=True)
1025 _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce)
1053 _checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce)
1026
1054
1027 # Track the shortest set of warning on the theory that bid
1055 # Track the shortest set of warning on the theory that bid
1028 # merge will correctly incorporate more information
1056 # merge will correctly incorporate more information
1029 if diverge is None or len(diverge1) < len(diverge):
1057 if diverge is None or len(diverge1) < len(diverge):
1030 diverge = diverge1
1058 diverge = diverge1
1031 if renamedelete is None or len(renamedelete) < len(renamedelete1):
1059 if renamedelete is None or len(renamedelete) < len(renamedelete1):
1032 renamedelete = renamedelete1
1060 renamedelete = renamedelete1
1033
1061
1034 for f, a in sorted(actions.iteritems()):
1062 for f, a in sorted(actions.iteritems()):
1035 m, args, msg = a
1063 m, args, msg = a
1036 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
1064 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
1037 if f in fbids:
1065 if f in fbids:
1038 d = fbids[f]
1066 d = fbids[f]
1039 if m in d:
1067 if m in d:
1040 d[m].append(a)
1068 d[m].append(a)
1041 else:
1069 else:
1042 d[m] = [a]
1070 d[m] = [a]
1043 else:
1071 else:
1044 fbids[f] = {m: [a]}
1072 fbids[f] = {m: [a]}
1045
1073
1046 # Pick the best bid for each file
1074 # Pick the best bid for each file
1047 repo.ui.note(_('\nauction for merging merge bids\n'))
1075 repo.ui.note(_('\nauction for merging merge bids\n'))
1048 actions = {}
1076 actions = {}
1049 dms = [] # filenames that have dm actions
1077 dms = [] # filenames that have dm actions
1050 for f, bids in sorted(fbids.items()):
1078 for f, bids in sorted(fbids.items()):
1051 # bids is a mapping from action method to list af actions
1079 # bids is a mapping from action method to list af actions
1052 # Consensus?
1080 # Consensus?
1053 if len(bids) == 1: # all bids are the same kind of method
1081 if len(bids) == 1: # all bids are the same kind of method
1054 m, l = list(bids.items())[0]
1082 m, l = list(bids.items())[0]
1055 if all(a == l[0] for a in l[1:]): # len(bids) is > 1
1083 if all(a == l[0] for a in l[1:]): # len(bids) is > 1
1056 repo.ui.note(_(" %s: consensus for %s\n") % (f, m))
1084 repo.ui.note(_(" %s: consensus for %s\n") % (f, m))
1057 actions[f] = l[0]
1085 actions[f] = l[0]
1058 if m == 'dm':
1086 if m == 'dm':
1059 dms.append(f)
1087 dms.append(f)
1060 continue
1088 continue
1061 # If keep is an option, just do it.
1089 # If keep is an option, just do it.
1062 if 'k' in bids:
1090 if 'k' in bids:
1063 repo.ui.note(_(" %s: picking 'keep' action\n") % f)
1091 repo.ui.note(_(" %s: picking 'keep' action\n") % f)
1064 actions[f] = bids['k'][0]
1092 actions[f] = bids['k'][0]
1065 continue
1093 continue
1066 # If there are gets and they all agree [how could they not?], do it.
1094 # If there are gets and they all agree [how could they not?], do it.
1067 if 'g' in bids:
1095 if 'g' in bids:
1068 ga0 = bids['g'][0]
1096 ga0 = bids['g'][0]
1069 if all(a == ga0 for a in bids['g'][1:]):
1097 if all(a == ga0 for a in bids['g'][1:]):
1070 repo.ui.note(_(" %s: picking 'get' action\n") % f)
1098 repo.ui.note(_(" %s: picking 'get' action\n") % f)
1071 actions[f] = ga0
1099 actions[f] = ga0
1072 continue
1100 continue
1073 # TODO: Consider other simple actions such as mode changes
1101 # TODO: Consider other simple actions such as mode changes
1074 # Handle inefficient democrazy.
1102 # Handle inefficient democrazy.
1075 repo.ui.note(_(' %s: multiple bids for merge action:\n') % f)
1103 repo.ui.note(_(' %s: multiple bids for merge action:\n') % f)
1076 for m, l in sorted(bids.items()):
1104 for m, l in sorted(bids.items()):
1077 for _f, args, msg in l:
1105 for _f, args, msg in l:
1078 repo.ui.note(' %s -> %s\n' % (msg, m))
1106 repo.ui.note(' %s -> %s\n' % (msg, m))
1079 # Pick random action. TODO: Instead, prompt user when resolving
1107 # Pick random action. TODO: Instead, prompt user when resolving
1080 m, l = list(bids.items())[0]
1108 m, l = list(bids.items())[0]
1081 repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
1109 repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
1082 (f, m))
1110 (f, m))
1083 actions[f] = l[0]
1111 actions[f] = l[0]
1084 if m == 'dm':
1112 if m == 'dm':
1085 dms.append(f)
1113 dms.append(f)
1086 continue
1114 continue
1087 # Work around 'dm' that can cause multiple actions for the same file
1115 # Work around 'dm' that can cause multiple actions for the same file
1088 for f in dms:
1116 for f in dms:
1089 dm, (f0, flags), msg = actions[f]
1117 dm, (f0, flags), msg = actions[f]
1090 assert dm == 'dm', dm
1118 assert dm == 'dm', dm
1091 if f0 in actions and actions[f0][0] == 'r':
1119 if f0 in actions and actions[f0][0] == 'r':
1092 # We have one bid for removing a file and another for moving it.
1120 # We have one bid for removing a file and another for moving it.
1093 # These two could be merged as first move and then delete ...
1121 # These two could be merged as first move and then delete ...
1094 # but instead drop moving and just delete.
1122 # but instead drop moving and just delete.
1095 del actions[f]
1123 del actions[f]
1096 repo.ui.note(_('end of auction\n\n'))
1124 repo.ui.note(_('end of auction\n\n'))
1097
1125
1098 _resolvetrivial(repo, wctx, mctx, ancestors[0], actions)
1126 _resolvetrivial(repo, wctx, mctx, ancestors[0], actions)
1099
1127
1100 if wctx.rev() is None:
1128 if wctx.rev() is None:
1101 fractions = _forgetremoved(wctx, mctx, branchmerge)
1129 fractions = _forgetremoved(wctx, mctx, branchmerge)
1102 actions.update(fractions)
1130 actions.update(fractions)
1103
1131
1104 prunedactions = sparse.filterupdatesactions(repo, wctx, mctx, branchmerge,
1132 prunedactions = sparse.filterupdatesactions(repo, wctx, mctx, branchmerge,
1105 actions)
1133 actions)
1106
1134
1107 return prunedactions, diverge, renamedelete
1135 return prunedactions, diverge, renamedelete
1108
1136
1109 def _getcwd():
1137 def _getcwd():
1110 try:
1138 try:
1111 return pycompat.getcwd()
1139 return pycompat.getcwd()
1112 except OSError as err:
1140 except OSError as err:
1113 if err.errno == errno.ENOENT:
1141 if err.errno == errno.ENOENT:
1114 return None
1142 return None
1115 raise
1143 raise
1116
1144
1117 def batchremove(repo, wctx, actions):
1145 def batchremove(repo, wctx, actions):
1118 """apply removes to the working directory
1146 """apply removes to the working directory
1119
1147
1120 yields tuples for progress updates
1148 yields tuples for progress updates
1121 """
1149 """
1122 verbose = repo.ui.verbose
1150 verbose = repo.ui.verbose
1123 cwd = _getcwd()
1151 cwd = _getcwd()
1124 i = 0
1152 i = 0
1125 for f, args, msg in actions:
1153 for f, args, msg in actions:
1126 repo.ui.debug(" %s: %s -> r\n" % (f, msg))
1154 repo.ui.debug(" %s: %s -> r\n" % (f, msg))
1127 if verbose:
1155 if verbose:
1128 repo.ui.note(_("removing %s\n") % f)
1156 repo.ui.note(_("removing %s\n") % f)
1129 wctx[f].audit()
1157 wctx[f].audit()
1130 try:
1158 try:
1131 wctx[f].remove(ignoremissing=True)
1159 wctx[f].remove(ignoremissing=True)
1132 except OSError as inst:
1160 except OSError as inst:
1133 repo.ui.warn(_("update failed to remove %s: %s!\n") %
1161 repo.ui.warn(_("update failed to remove %s: %s!\n") %
1134 (f, inst.strerror))
1162 (f, inst.strerror))
1135 if i == 100:
1163 if i == 100:
1136 yield i, f
1164 yield i, f
1137 i = 0
1165 i = 0
1138 i += 1
1166 i += 1
1139 if i > 0:
1167 if i > 0:
1140 yield i, f
1168 yield i, f
1141
1169
1142 if cwd and not _getcwd():
1170 if cwd and not _getcwd():
1143 # cwd was removed in the course of removing files; print a helpful
1171 # cwd was removed in the course of removing files; print a helpful
1144 # warning.
1172 # warning.
1145 repo.ui.warn(_("current directory was removed\n"
1173 repo.ui.warn(_("current directory was removed\n"
1146 "(consider changing to repo root: %s)\n") % repo.root)
1174 "(consider changing to repo root: %s)\n") % repo.root)
1147
1175
1148 # It's necessary to flush here in case we're inside a worker fork and will
1176 # It's necessary to flush here in case we're inside a worker fork and will
1149 # quit after this function.
1177 # quit after this function.
1150 wctx.flushall()
1178 wctx.flushall()
1151
1179
1152 def batchget(repo, mctx, wctx, actions):
1180 def batchget(repo, mctx, wctx, actions):
1153 """apply gets to the working directory
1181 """apply gets to the working directory
1154
1182
1155 mctx is the context to get from
1183 mctx is the context to get from
1156
1184
1157 yields tuples for progress updates
1185 yields tuples for progress updates
1158 """
1186 """
1159 verbose = repo.ui.verbose
1187 verbose = repo.ui.verbose
1160 fctx = mctx.filectx
1188 fctx = mctx.filectx
1161 ui = repo.ui
1189 ui = repo.ui
1162 i = 0
1190 i = 0
1163 with repo.wvfs.backgroundclosing(ui, expectedcount=len(actions)):
1191 with repo.wvfs.backgroundclosing(ui, expectedcount=len(actions)):
1164 for f, (flags, backup), msg in actions:
1192 for f, (flags, backup), msg in actions:
1165 repo.ui.debug(" %s: %s -> g\n" % (f, msg))
1193 repo.ui.debug(" %s: %s -> g\n" % (f, msg))
1166 if verbose:
1194 if verbose:
1167 repo.ui.note(_("getting %s\n") % f)
1195 repo.ui.note(_("getting %s\n") % f)
1168
1196
1169 if backup:
1197 if backup:
1170 # If a file or directory exists with the same name, back that
1198 # If a file or directory exists with the same name, back that
1171 # up. Otherwise, look to see if there is a file that conflicts
1199 # up. Otherwise, look to see if there is a file that conflicts
1172 # with a directory this file is in, and if so, back that up.
1200 # with a directory this file is in, and if so, back that up.
1173 absf = repo.wjoin(f)
1201 absf = repo.wjoin(f)
1174 if not repo.wvfs.lexists(f):
1202 if not repo.wvfs.lexists(f):
1175 for p in util.finddirs(f):
1203 for p in util.finddirs(f):
1176 if repo.wvfs.isfileorlink(p):
1204 if repo.wvfs.isfileorlink(p):
1177 absf = repo.wjoin(p)
1205 absf = repo.wjoin(p)
1178 break
1206 break
1179 orig = scmutil.origpath(ui, repo, absf)
1207 orig = scmutil.origpath(ui, repo, absf)
1180 if repo.wvfs.lexists(absf):
1208 if repo.wvfs.lexists(absf):
1181 util.rename(absf, orig)
1209 util.rename(absf, orig)
1182 wctx[f].clearunknown()
1210 wctx[f].clearunknown()
1183 wctx[f].write(fctx(f).data(), flags, backgroundclose=True)
1211 wctx[f].write(fctx(f).data(), flags, backgroundclose=True)
1184 if i == 100:
1212 if i == 100:
1185 yield i, f
1213 yield i, f
1186 i = 0
1214 i = 0
1187 i += 1
1215 i += 1
1188 if i > 0:
1216 if i > 0:
1189 yield i, f
1217 yield i, f
1190
1218
1191 # It's necessary to flush here in case we're inside a worker fork and will
1219 # It's necessary to flush here in case we're inside a worker fork and will
1192 # quit after this function.
1220 # quit after this function.
1193 wctx.flushall()
1221 wctx.flushall()
1194
1222
1195 def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None):
1223 def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None):
1196 """apply the merge action list to the working directory
1224 """apply the merge action list to the working directory
1197
1225
1198 wctx is the working copy context
1226 wctx is the working copy context
1199 mctx is the context to be merged into the working copy
1227 mctx is the context to be merged into the working copy
1200
1228
1201 Return a tuple of counts (updated, merged, removed, unresolved) that
1229 Return a tuple of counts (updated, merged, removed, unresolved) that
1202 describes how many files were affected by the update.
1230 describes how many files were affected by the update.
1203 """
1231 """
1204
1232
1205 updated, merged, removed = 0, 0, 0
1233 updated, merged, removed = 0, 0, 0
1206 ms = mergestate.clean(repo, wctx.p1().node(), mctx.node(), labels)
1234 ms = mergestate.clean(repo, wctx.p1().node(), mctx.node(), labels)
1207 moves = []
1235 moves = []
1208 for m, l in actions.items():
1236 for m, l in actions.items():
1209 l.sort()
1237 l.sort()
1210
1238
1211 # 'cd' and 'dc' actions are treated like other merge conflicts
1239 # 'cd' and 'dc' actions are treated like other merge conflicts
1212 mergeactions = sorted(actions['cd'])
1240 mergeactions = sorted(actions['cd'])
1213 mergeactions.extend(sorted(actions['dc']))
1241 mergeactions.extend(sorted(actions['dc']))
1214 mergeactions.extend(actions['m'])
1242 mergeactions.extend(actions['m'])
1215 for f, args, msg in mergeactions:
1243 for f, args, msg in mergeactions:
1216 f1, f2, fa, move, anc = args
1244 f1, f2, fa, move, anc = args
1217 if f == '.hgsubstate': # merged internally
1245 if f == '.hgsubstate': # merged internally
1218 continue
1246 continue
1219 if f1 is None:
1247 if f1 is None:
1220 fcl = filemerge.absentfilectx(wctx, fa)
1248 fcl = filemerge.absentfilectx(wctx, fa)
1221 else:
1249 else:
1222 repo.ui.debug(" preserving %s for resolve of %s\n" % (f1, f))
1250 repo.ui.debug(" preserving %s for resolve of %s\n" % (f1, f))
1223 fcl = wctx[f1]
1251 fcl = wctx[f1]
1224 if f2 is None:
1252 if f2 is None:
1225 fco = filemerge.absentfilectx(mctx, fa)
1253 fco = filemerge.absentfilectx(mctx, fa)
1226 else:
1254 else:
1227 fco = mctx[f2]
1255 fco = mctx[f2]
1228 actx = repo[anc]
1256 actx = repo[anc]
1229 if fa in actx:
1257 if fa in actx:
1230 fca = actx[fa]
1258 fca = actx[fa]
1231 else:
1259 else:
1232 # TODO: move to absentfilectx
1260 # TODO: move to absentfilectx
1233 fca = repo.filectx(f1, fileid=nullrev)
1261 fca = repo.filectx(f1, fileid=nullrev)
1234 ms.add(fcl, fco, fca, f)
1262 ms.add(fcl, fco, fca, f)
1235 if f1 != f and move:
1263 if f1 != f and move:
1236 moves.append(f1)
1264 moves.append(f1)
1237
1265
1238 _updating = _('updating')
1266 _updating = _('updating')
1239 _files = _('files')
1267 _files = _('files')
1240 progress = repo.ui.progress
1268 progress = repo.ui.progress
1241
1269
1242 # remove renamed files after safely stored
1270 # remove renamed files after safely stored
1243 for f in moves:
1271 for f in moves:
1244 if wctx[f].lexists():
1272 if wctx[f].lexists():
1245 repo.ui.debug("removing %s\n" % f)
1273 repo.ui.debug("removing %s\n" % f)
1246 wctx[f].audit()
1274 wctx[f].audit()
1247 wctx[f].remove()
1275 wctx[f].remove()
1248
1276
1249 numupdates = sum(len(l) for m, l in actions.items() if m != 'k')
1277 numupdates = sum(len(l) for m, l in actions.items() if m != 'k')
1250 z = 0
1278 z = 0
1251
1279
1252 if [a for a in actions['r'] if a[0] == '.hgsubstate']:
1280 if [a for a in actions['r'] if a[0] == '.hgsubstate']:
1253 subrepo.submerge(repo, wctx, mctx, wctx, overwrite, labels)
1281 subrepo.submerge(repo, wctx, mctx, wctx, overwrite, labels)
1254
1282
1255 # record path conflicts
1283 # record path conflicts
1256 for f, args, msg in actions['p']:
1284 for f, args, msg in actions['p']:
1257 f1, fo = args
1285 f1, fo = args
1258 s = repo.ui.status
1286 s = repo.ui.status
1259 s(_("%s: path conflict - a file or link has the same name as a "
1287 s(_("%s: path conflict - a file or link has the same name as a "
1260 "directory\n") % f)
1288 "directory\n") % f)
1261 if fo == 'l':
1289 if fo == 'l':
1262 s(_("the local file has been renamed to %s\n") % f1)
1290 s(_("the local file has been renamed to %s\n") % f1)
1263 else:
1291 else:
1264 s(_("the remote file has been renamed to %s\n") % f1)
1292 s(_("the remote file has been renamed to %s\n") % f1)
1265 s(_("resolve manually then use 'hg resolve --mark %s'\n") % f)
1293 s(_("resolve manually then use 'hg resolve --mark %s'\n") % f)
1266 ms.addpath(f, f1, fo)
1294 ms.addpath(f, f1, fo)
1267 z += 1
1295 z += 1
1268 progress(_updating, z, item=f, total=numupdates, unit=_files)
1296 progress(_updating, z, item=f, total=numupdates, unit=_files)
1269
1297
1270 # remove in parallel (must come before resolving path conflicts and getting)
1298 # remove in parallel (must come before resolving path conflicts and getting)
1271 prog = worker.worker(repo.ui, 0.001, batchremove, (repo, wctx),
1299 prog = worker.worker(repo.ui, 0.001, batchremove, (repo, wctx),
1272 actions['r'])
1300 actions['r'])
1273 for i, item in prog:
1301 for i, item in prog:
1274 z += i
1302 z += i
1275 progress(_updating, z, item=item, total=numupdates, unit=_files)
1303 progress(_updating, z, item=item, total=numupdates, unit=_files)
1276 removed = len(actions['r'])
1304 removed = len(actions['r'])
1277
1305
1278 # resolve path conflicts (must come before getting)
1306 # resolve path conflicts (must come before getting)
1279 for f, args, msg in actions['pr']:
1307 for f, args, msg in actions['pr']:
1280 repo.ui.debug(" %s: %s -> pr\n" % (f, msg))
1308 repo.ui.debug(" %s: %s -> pr\n" % (f, msg))
1281 f0, = args
1309 f0, = args
1282 if wctx[f0].lexists():
1310 if wctx[f0].lexists():
1283 repo.ui.note(_("moving %s to %s\n") % (f0, f))
1311 repo.ui.note(_("moving %s to %s\n") % (f0, f))
1284 wctx[f].audit()
1312 wctx[f].audit()
1285 wctx[f].write(wctx.filectx(f0).data(), wctx.filectx(f0).flags())
1313 wctx[f].write(wctx.filectx(f0).data(), wctx.filectx(f0).flags())
1286 wctx[f0].remove()
1314 wctx[f0].remove()
1287 z += 1
1315 z += 1
1288 progress(_updating, z, item=f, total=numupdates, unit=_files)
1316 progress(_updating, z, item=f, total=numupdates, unit=_files)
1289
1317
1290 # We should flush before forking into worker processes, since those workers
1318 # We should flush before forking into worker processes, since those workers
1291 # flush when they complete, and we don't want to duplicate work.
1319 # flush when they complete, and we don't want to duplicate work.
1292 wctx.flushall()
1320 wctx.flushall()
1293
1321
1294 # get in parallel
1322 # get in parallel
1295 prog = worker.worker(repo.ui, 0.001, batchget, (repo, mctx, wctx),
1323 prog = worker.worker(repo.ui, 0.001, batchget, (repo, mctx, wctx),
1296 actions['g'])
1324 actions['g'])
1297 for i, item in prog:
1325 for i, item in prog:
1298 z += i
1326 z += i
1299 progress(_updating, z, item=item, total=numupdates, unit=_files)
1327 progress(_updating, z, item=item, total=numupdates, unit=_files)
1300 updated = len(actions['g'])
1328 updated = len(actions['g'])
1301
1329
1302 if [a for a in actions['g'] if a[0] == '.hgsubstate']:
1330 if [a for a in actions['g'] if a[0] == '.hgsubstate']:
1303 subrepo.submerge(repo, wctx, mctx, wctx, overwrite, labels)
1331 subrepo.submerge(repo, wctx, mctx, wctx, overwrite, labels)
1304
1332
1305 # forget (manifest only, just log it) (must come first)
1333 # forget (manifest only, just log it) (must come first)
1306 for f, args, msg in actions['f']:
1334 for f, args, msg in actions['f']:
1307 repo.ui.debug(" %s: %s -> f\n" % (f, msg))
1335 repo.ui.debug(" %s: %s -> f\n" % (f, msg))
1308 z += 1
1336 z += 1
1309 progress(_updating, z, item=f, total=numupdates, unit=_files)
1337 progress(_updating, z, item=f, total=numupdates, unit=_files)
1310
1338
1311 # re-add (manifest only, just log it)
1339 # re-add (manifest only, just log it)
1312 for f, args, msg in actions['a']:
1340 for f, args, msg in actions['a']:
1313 repo.ui.debug(" %s: %s -> a\n" % (f, msg))
1341 repo.ui.debug(" %s: %s -> a\n" % (f, msg))
1314 z += 1
1342 z += 1
1315 progress(_updating, z, item=f, total=numupdates, unit=_files)
1343 progress(_updating, z, item=f, total=numupdates, unit=_files)
1316
1344
1317 # re-add/mark as modified (manifest only, just log it)
1345 # re-add/mark as modified (manifest only, just log it)
1318 for f, args, msg in actions['am']:
1346 for f, args, msg in actions['am']:
1319 repo.ui.debug(" %s: %s -> am\n" % (f, msg))
1347 repo.ui.debug(" %s: %s -> am\n" % (f, msg))
1320 z += 1
1348 z += 1
1321 progress(_updating, z, item=f, total=numupdates, unit=_files)
1349 progress(_updating, z, item=f, total=numupdates, unit=_files)
1322
1350
1323 # keep (noop, just log it)
1351 # keep (noop, just log it)
1324 for f, args, msg in actions['k']:
1352 for f, args, msg in actions['k']:
1325 repo.ui.debug(" %s: %s -> k\n" % (f, msg))
1353 repo.ui.debug(" %s: %s -> k\n" % (f, msg))
1326 # no progress
1354 # no progress
1327
1355
1328 # directory rename, move local
1356 # directory rename, move local
1329 for f, args, msg in actions['dm']:
1357 for f, args, msg in actions['dm']:
1330 repo.ui.debug(" %s: %s -> dm\n" % (f, msg))
1358 repo.ui.debug(" %s: %s -> dm\n" % (f, msg))
1331 z += 1
1359 z += 1
1332 progress(_updating, z, item=f, total=numupdates, unit=_files)
1360 progress(_updating, z, item=f, total=numupdates, unit=_files)
1333 f0, flags = args
1361 f0, flags = args
1334 repo.ui.note(_("moving %s to %s\n") % (f0, f))
1362 repo.ui.note(_("moving %s to %s\n") % (f0, f))
1335 wctx[f].audit()
1363 wctx[f].audit()
1336 wctx[f].write(wctx.filectx(f0).data(), flags)
1364 wctx[f].write(wctx.filectx(f0).data(), flags)
1337 wctx[f0].remove()
1365 wctx[f0].remove()
1338 updated += 1
1366 updated += 1
1339
1367
1340 # local directory rename, get
1368 # local directory rename, get
1341 for f, args, msg in actions['dg']:
1369 for f, args, msg in actions['dg']:
1342 repo.ui.debug(" %s: %s -> dg\n" % (f, msg))
1370 repo.ui.debug(" %s: %s -> dg\n" % (f, msg))
1343 z += 1
1371 z += 1
1344 progress(_updating, z, item=f, total=numupdates, unit=_files)
1372 progress(_updating, z, item=f, total=numupdates, unit=_files)
1345 f0, flags = args
1373 f0, flags = args
1346 repo.ui.note(_("getting %s to %s\n") % (f0, f))
1374 repo.ui.note(_("getting %s to %s\n") % (f0, f))
1347 wctx[f].write(mctx.filectx(f0).data(), flags)
1375 wctx[f].write(mctx.filectx(f0).data(), flags)
1348 updated += 1
1376 updated += 1
1349
1377
1350 # exec
1378 # exec
1351 for f, args, msg in actions['e']:
1379 for f, args, msg in actions['e']:
1352 repo.ui.debug(" %s: %s -> e\n" % (f, msg))
1380 repo.ui.debug(" %s: %s -> e\n" % (f, msg))
1353 z += 1
1381 z += 1
1354 progress(_updating, z, item=f, total=numupdates, unit=_files)
1382 progress(_updating, z, item=f, total=numupdates, unit=_files)
1355 flags, = args
1383 flags, = args
1356 wctx[f].audit()
1384 wctx[f].audit()
1357 wctx[f].setflags('l' in flags, 'x' in flags)
1385 wctx[f].setflags('l' in flags, 'x' in flags)
1358 updated += 1
1386 updated += 1
1359
1387
1360 # the ordering is important here -- ms.mergedriver will raise if the merge
1388 # the ordering is important here -- ms.mergedriver will raise if the merge
1361 # driver has changed, and we want to be able to bypass it when overwrite is
1389 # driver has changed, and we want to be able to bypass it when overwrite is
1362 # True
1390 # True
1363 usemergedriver = not overwrite and mergeactions and ms.mergedriver
1391 usemergedriver = not overwrite and mergeactions and ms.mergedriver
1364
1392
1365 if usemergedriver:
1393 if usemergedriver:
1366 ms.commit()
1394 ms.commit()
1367 proceed = driverpreprocess(repo, ms, wctx, labels=labels)
1395 proceed = driverpreprocess(repo, ms, wctx, labels=labels)
1368 # the driver might leave some files unresolved
1396 # the driver might leave some files unresolved
1369 unresolvedf = set(ms.unresolved())
1397 unresolvedf = set(ms.unresolved())
1370 if not proceed:
1398 if not proceed:
1371 # XXX setting unresolved to at least 1 is a hack to make sure we
1399 # XXX setting unresolved to at least 1 is a hack to make sure we
1372 # error out
1400 # error out
1373 return updated, merged, removed, max(len(unresolvedf), 1)
1401 return updated, merged, removed, max(len(unresolvedf), 1)
1374 newactions = []
1402 newactions = []
1375 for f, args, msg in mergeactions:
1403 for f, args, msg in mergeactions:
1376 if f in unresolvedf:
1404 if f in unresolvedf:
1377 newactions.append((f, args, msg))
1405 newactions.append((f, args, msg))
1378 mergeactions = newactions
1406 mergeactions = newactions
1379
1407
1380 # premerge
1408 # premerge
1381 tocomplete = []
1409 tocomplete = []
1382 for f, args, msg in mergeactions:
1410 for f, args, msg in mergeactions:
1383 repo.ui.debug(" %s: %s -> m (premerge)\n" % (f, msg))
1411 repo.ui.debug(" %s: %s -> m (premerge)\n" % (f, msg))
1384 z += 1
1412 z += 1
1385 progress(_updating, z, item=f, total=numupdates, unit=_files)
1413 progress(_updating, z, item=f, total=numupdates, unit=_files)
1386 if f == '.hgsubstate': # subrepo states need updating
1414 if f == '.hgsubstate': # subrepo states need updating
1387 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
1415 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
1388 overwrite, labels)
1416 overwrite, labels)
1389 continue
1417 continue
1390 wctx[f].audit()
1418 wctx[f].audit()
1391 complete, r = ms.preresolve(f, wctx)
1419 complete, r = ms.preresolve(f, wctx)
1392 if not complete:
1420 if not complete:
1393 numupdates += 1
1421 numupdates += 1
1394 tocomplete.append((f, args, msg))
1422 tocomplete.append((f, args, msg))
1395
1423
1396 # merge
1424 # merge
1397 for f, args, msg in tocomplete:
1425 for f, args, msg in tocomplete:
1398 repo.ui.debug(" %s: %s -> m (merge)\n" % (f, msg))
1426 repo.ui.debug(" %s: %s -> m (merge)\n" % (f, msg))
1399 z += 1
1427 z += 1
1400 progress(_updating, z, item=f, total=numupdates, unit=_files)
1428 progress(_updating, z, item=f, total=numupdates, unit=_files)
1401 ms.resolve(f, wctx)
1429 ms.resolve(f, wctx)
1402
1430
1403 ms.commit()
1431 ms.commit()
1404
1432
1405 unresolved = ms.unresolvedcount()
1433 unresolved = ms.unresolvedcount()
1406
1434
1407 if usemergedriver and not unresolved and ms.mdstate() != 's':
1435 if usemergedriver and not unresolved and ms.mdstate() != 's':
1408 if not driverconclude(repo, ms, wctx, labels=labels):
1436 if not driverconclude(repo, ms, wctx, labels=labels):
1409 # XXX setting unresolved to at least 1 is a hack to make sure we
1437 # XXX setting unresolved to at least 1 is a hack to make sure we
1410 # error out
1438 # error out
1411 unresolved = max(unresolved, 1)
1439 unresolved = max(unresolved, 1)
1412
1440
1413 ms.commit()
1441 ms.commit()
1414
1442
1415 msupdated, msmerged, msremoved = ms.counts()
1443 msupdated, msmerged, msremoved = ms.counts()
1416 updated += msupdated
1444 updated += msupdated
1417 merged += msmerged
1445 merged += msmerged
1418 removed += msremoved
1446 removed += msremoved
1419
1447
1420 extraactions = ms.actions()
1448 extraactions = ms.actions()
1421 if extraactions:
1449 if extraactions:
1422 mfiles = set(a[0] for a in actions['m'])
1450 mfiles = set(a[0] for a in actions['m'])
1423 for k, acts in extraactions.iteritems():
1451 for k, acts in extraactions.iteritems():
1424 actions[k].extend(acts)
1452 actions[k].extend(acts)
1425 # Remove these files from actions['m'] as well. This is important
1453 # Remove these files from actions['m'] as well. This is important
1426 # because in recordupdates, files in actions['m'] are processed
1454 # because in recordupdates, files in actions['m'] are processed
1427 # after files in other actions, and the merge driver might add
1455 # after files in other actions, and the merge driver might add
1428 # files to those actions via extraactions above. This can lead to a
1456 # files to those actions via extraactions above. This can lead to a
1429 # file being recorded twice, with poor results. This is especially
1457 # file being recorded twice, with poor results. This is especially
1430 # problematic for actions['r'] (currently only possible with the
1458 # problematic for actions['r'] (currently only possible with the
1431 # merge driver in the initial merge process; interrupted merges
1459 # merge driver in the initial merge process; interrupted merges
1432 # don't go through this flow).
1460 # don't go through this flow).
1433 #
1461 #
1434 # The real fix here is to have indexes by both file and action so
1462 # The real fix here is to have indexes by both file and action so
1435 # that when the action for a file is changed it is automatically
1463 # that when the action for a file is changed it is automatically
1436 # reflected in the other action lists. But that involves a more
1464 # reflected in the other action lists. But that involves a more
1437 # complex data structure, so this will do for now.
1465 # complex data structure, so this will do for now.
1438 #
1466 #
1439 # We don't need to do the same operation for 'dc' and 'cd' because
1467 # We don't need to do the same operation for 'dc' and 'cd' because
1440 # those lists aren't consulted again.
1468 # those lists aren't consulted again.
1441 mfiles.difference_update(a[0] for a in acts)
1469 mfiles.difference_update(a[0] for a in acts)
1442
1470
1443 actions['m'] = [a for a in actions['m'] if a[0] in mfiles]
1471 actions['m'] = [a for a in actions['m'] if a[0] in mfiles]
1444
1472
1445 progress(_updating, None, total=numupdates, unit=_files)
1473 progress(_updating, None, total=numupdates, unit=_files)
1446
1474
1447 return updated, merged, removed, unresolved
1475 return updated, merged, removed, unresolved
1448
1476
1449 def recordupdates(repo, actions, branchmerge):
1477 def recordupdates(repo, actions, branchmerge):
1450 "record merge actions to the dirstate"
1478 "record merge actions to the dirstate"
1451 # remove (must come first)
1479 # remove (must come first)
1452 for f, args, msg in actions.get('r', []):
1480 for f, args, msg in actions.get('r', []):
1453 if branchmerge:
1481 if branchmerge:
1454 repo.dirstate.remove(f)
1482 repo.dirstate.remove(f)
1455 else:
1483 else:
1456 repo.dirstate.drop(f)
1484 repo.dirstate.drop(f)
1457
1485
1458 # forget (must come first)
1486 # forget (must come first)
1459 for f, args, msg in actions.get('f', []):
1487 for f, args, msg in actions.get('f', []):
1460 repo.dirstate.drop(f)
1488 repo.dirstate.drop(f)
1461
1489
1462 # resolve path conflicts
1490 # resolve path conflicts
1463 for f, args, msg in actions.get('pr', []):
1491 for f, args, msg in actions.get('pr', []):
1464 f0, = args
1492 f0, = args
1465 origf0 = repo.dirstate.copied(f0) or f0
1493 origf0 = repo.dirstate.copied(f0) or f0
1466 repo.dirstate.add(f)
1494 repo.dirstate.add(f)
1467 repo.dirstate.copy(origf0, f)
1495 repo.dirstate.copy(origf0, f)
1468 if f0 == origf0:
1496 if f0 == origf0:
1469 repo.dirstate.remove(f0)
1497 repo.dirstate.remove(f0)
1470 else:
1498 else:
1471 repo.dirstate.drop(f0)
1499 repo.dirstate.drop(f0)
1472
1500
1473 # re-add
1501 # re-add
1474 for f, args, msg in actions.get('a', []):
1502 for f, args, msg in actions.get('a', []):
1475 repo.dirstate.add(f)
1503 repo.dirstate.add(f)
1476
1504
1477 # re-add/mark as modified
1505 # re-add/mark as modified
1478 for f, args, msg in actions.get('am', []):
1506 for f, args, msg in actions.get('am', []):
1479 if branchmerge:
1507 if branchmerge:
1480 repo.dirstate.normallookup(f)
1508 repo.dirstate.normallookup(f)
1481 else:
1509 else:
1482 repo.dirstate.add(f)
1510 repo.dirstate.add(f)
1483
1511
1484 # exec change
1512 # exec change
1485 for f, args, msg in actions.get('e', []):
1513 for f, args, msg in actions.get('e', []):
1486 repo.dirstate.normallookup(f)
1514 repo.dirstate.normallookup(f)
1487
1515
1488 # keep
1516 # keep
1489 for f, args, msg in actions.get('k', []):
1517 for f, args, msg in actions.get('k', []):
1490 pass
1518 pass
1491
1519
1492 # get
1520 # get
1493 for f, args, msg in actions.get('g', []):
1521 for f, args, msg in actions.get('g', []):
1494 if branchmerge:
1522 if branchmerge:
1495 repo.dirstate.otherparent(f)
1523 repo.dirstate.otherparent(f)
1496 else:
1524 else:
1497 repo.dirstate.normal(f)
1525 repo.dirstate.normal(f)
1498
1526
1499 # merge
1527 # merge
1500 for f, args, msg in actions.get('m', []):
1528 for f, args, msg in actions.get('m', []):
1501 f1, f2, fa, move, anc = args
1529 f1, f2, fa, move, anc = args
1502 if branchmerge:
1530 if branchmerge:
1503 # We've done a branch merge, mark this file as merged
1531 # We've done a branch merge, mark this file as merged
1504 # so that we properly record the merger later
1532 # so that we properly record the merger later
1505 repo.dirstate.merge(f)
1533 repo.dirstate.merge(f)
1506 if f1 != f2: # copy/rename
1534 if f1 != f2: # copy/rename
1507 if move:
1535 if move:
1508 repo.dirstate.remove(f1)
1536 repo.dirstate.remove(f1)
1509 if f1 != f:
1537 if f1 != f:
1510 repo.dirstate.copy(f1, f)
1538 repo.dirstate.copy(f1, f)
1511 else:
1539 else:
1512 repo.dirstate.copy(f2, f)
1540 repo.dirstate.copy(f2, f)
1513 else:
1541 else:
1514 # We've update-merged a locally modified file, so
1542 # We've update-merged a locally modified file, so
1515 # we set the dirstate to emulate a normal checkout
1543 # we set the dirstate to emulate a normal checkout
1516 # of that file some time in the past. Thus our
1544 # of that file some time in the past. Thus our
1517 # merge will appear as a normal local file
1545 # merge will appear as a normal local file
1518 # modification.
1546 # modification.
1519 if f2 == f: # file not locally copied/moved
1547 if f2 == f: # file not locally copied/moved
1520 repo.dirstate.normallookup(f)
1548 repo.dirstate.normallookup(f)
1521 if move:
1549 if move:
1522 repo.dirstate.drop(f1)
1550 repo.dirstate.drop(f1)
1523
1551
1524 # directory rename, move local
1552 # directory rename, move local
1525 for f, args, msg in actions.get('dm', []):
1553 for f, args, msg in actions.get('dm', []):
1526 f0, flag = args
1554 f0, flag = args
1527 if branchmerge:
1555 if branchmerge:
1528 repo.dirstate.add(f)
1556 repo.dirstate.add(f)
1529 repo.dirstate.remove(f0)
1557 repo.dirstate.remove(f0)
1530 repo.dirstate.copy(f0, f)
1558 repo.dirstate.copy(f0, f)
1531 else:
1559 else:
1532 repo.dirstate.normal(f)
1560 repo.dirstate.normal(f)
1533 repo.dirstate.drop(f0)
1561 repo.dirstate.drop(f0)
1534
1562
1535 # directory rename, get
1563 # directory rename, get
1536 for f, args, msg in actions.get('dg', []):
1564 for f, args, msg in actions.get('dg', []):
1537 f0, flag = args
1565 f0, flag = args
1538 if branchmerge:
1566 if branchmerge:
1539 repo.dirstate.add(f)
1567 repo.dirstate.add(f)
1540 repo.dirstate.copy(f0, f)
1568 repo.dirstate.copy(f0, f)
1541 else:
1569 else:
1542 repo.dirstate.normal(f)
1570 repo.dirstate.normal(f)
1543
1571
1544 def update(repo, node, branchmerge, force, ancestor=None,
1572 def update(repo, node, branchmerge, force, ancestor=None,
1545 mergeancestor=False, labels=None, matcher=None, mergeforce=False,
1573 mergeancestor=False, labels=None, matcher=None, mergeforce=False,
1546 updatecheck=None, wc=None):
1574 updatecheck=None, wc=None):
1547 """
1575 """
1548 Perform a merge between the working directory and the given node
1576 Perform a merge between the working directory and the given node
1549
1577
1550 node = the node to update to
1578 node = the node to update to
1551 branchmerge = whether to merge between branches
1579 branchmerge = whether to merge between branches
1552 force = whether to force branch merging or file overwriting
1580 force = whether to force branch merging or file overwriting
1553 matcher = a matcher to filter file lists (dirstate not updated)
1581 matcher = a matcher to filter file lists (dirstate not updated)
1554 mergeancestor = whether it is merging with an ancestor. If true,
1582 mergeancestor = whether it is merging with an ancestor. If true,
1555 we should accept the incoming changes for any prompts that occur.
1583 we should accept the incoming changes for any prompts that occur.
1556 If false, merging with an ancestor (fast-forward) is only allowed
1584 If false, merging with an ancestor (fast-forward) is only allowed
1557 between different named branches. This flag is used by rebase extension
1585 between different named branches. This flag is used by rebase extension
1558 as a temporary fix and should be avoided in general.
1586 as a temporary fix and should be avoided in general.
1559 labels = labels to use for base, local and other
1587 labels = labels to use for base, local and other
1560 mergeforce = whether the merge was run with 'merge --force' (deprecated): if
1588 mergeforce = whether the merge was run with 'merge --force' (deprecated): if
1561 this is True, then 'force' should be True as well.
1589 this is True, then 'force' should be True as well.
1562
1590
1563 The table below shows all the behaviors of the update command
1591 The table below shows all the behaviors of the update command
1564 given the -c and -C or no options, whether the working directory
1592 given the -c and -C or no options, whether the working directory
1565 is dirty, whether a revision is specified, and the relationship of
1593 is dirty, whether a revision is specified, and the relationship of
1566 the parent rev to the target rev (linear or not). Match from top first. The
1594 the parent rev to the target rev (linear or not). Match from top first. The
1567 -n option doesn't exist on the command line, but represents the
1595 -n option doesn't exist on the command line, but represents the
1568 experimental.updatecheck=noconflict option.
1596 experimental.updatecheck=noconflict option.
1569
1597
1570 This logic is tested by test-update-branches.t.
1598 This logic is tested by test-update-branches.t.
1571
1599
1572 -c -C -n -m dirty rev linear | result
1600 -c -C -n -m dirty rev linear | result
1573 y y * * * * * | (1)
1601 y y * * * * * | (1)
1574 y * y * * * * | (1)
1602 y * y * * * * | (1)
1575 y * * y * * * | (1)
1603 y * * y * * * | (1)
1576 * y y * * * * | (1)
1604 * y y * * * * | (1)
1577 * y * y * * * | (1)
1605 * y * y * * * | (1)
1578 * * y y * * * | (1)
1606 * * y y * * * | (1)
1579 * * * * * n n | x
1607 * * * * * n n | x
1580 * * * * n * * | ok
1608 * * * * n * * | ok
1581 n n n n y * y | merge
1609 n n n n y * y | merge
1582 n n n n y y n | (2)
1610 n n n n y y n | (2)
1583 n n n y y * * | merge
1611 n n n y y * * | merge
1584 n n y n y * * | merge if no conflict
1612 n n y n y * * | merge if no conflict
1585 n y n n y * * | discard
1613 n y n n y * * | discard
1586 y n n n y * * | (3)
1614 y n n n y * * | (3)
1587
1615
1588 x = can't happen
1616 x = can't happen
1589 * = don't-care
1617 * = don't-care
1590 1 = incompatible options (checked in commands.py)
1618 1 = incompatible options (checked in commands.py)
1591 2 = abort: uncommitted changes (commit or update --clean to discard changes)
1619 2 = abort: uncommitted changes (commit or update --clean to discard changes)
1592 3 = abort: uncommitted changes (checked in commands.py)
1620 3 = abort: uncommitted changes (checked in commands.py)
1593
1621
1594 The merge is performed inside ``wc``, a workingctx-like objects. It defaults
1622 The merge is performed inside ``wc``, a workingctx-like objects. It defaults
1595 to repo[None] if None is passed.
1623 to repo[None] if None is passed.
1596
1624
1597 Return the same tuple as applyupdates().
1625 Return the same tuple as applyupdates().
1598 """
1626 """
1599 # Avoid cycle.
1627 # Avoid cycle.
1600 from . import sparse
1628 from . import sparse
1601
1629
1602 # This function used to find the default destination if node was None, but
1630 # This function used to find the default destination if node was None, but
1603 # that's now in destutil.py.
1631 # that's now in destutil.py.
1604 assert node is not None
1632 assert node is not None
1605 if not branchmerge and not force:
1633 if not branchmerge and not force:
1606 # TODO: remove the default once all callers that pass branchmerge=False
1634 # TODO: remove the default once all callers that pass branchmerge=False
1607 # and force=False pass a value for updatecheck. We may want to allow
1635 # and force=False pass a value for updatecheck. We may want to allow
1608 # updatecheck='abort' to better suppport some of these callers.
1636 # updatecheck='abort' to better suppport some of these callers.
1609 if updatecheck is None:
1637 if updatecheck is None:
1610 updatecheck = 'linear'
1638 updatecheck = 'linear'
1611 assert updatecheck in ('none', 'linear', 'noconflict')
1639 assert updatecheck in ('none', 'linear', 'noconflict')
1612 # If we're doing a partial update, we need to skip updating
1640 # If we're doing a partial update, we need to skip updating
1613 # the dirstate, so make a note of any partial-ness to the
1641 # the dirstate, so make a note of any partial-ness to the
1614 # update here.
1642 # update here.
1615 if matcher is None or matcher.always():
1643 if matcher is None or matcher.always():
1616 partial = False
1644 partial = False
1617 else:
1645 else:
1618 partial = True
1646 partial = True
1619 with repo.wlock():
1647 with repo.wlock():
1620 if wc is None:
1648 if wc is None:
1621 wc = repo[None]
1649 wc = repo[None]
1622 pl = wc.parents()
1650 pl = wc.parents()
1623 p1 = pl[0]
1651 p1 = pl[0]
1624 pas = [None]
1652 pas = [None]
1625 if ancestor is not None:
1653 if ancestor is not None:
1626 pas = [repo[ancestor]]
1654 pas = [repo[ancestor]]
1627
1655
1628 overwrite = force and not branchmerge
1656 overwrite = force and not branchmerge
1629
1657
1630 p2 = repo[node]
1658 p2 = repo[node]
1631 if pas[0] is None:
1659 if pas[0] is None:
1632 if repo.ui.configlist('merge', 'preferancestor') == ['*']:
1660 if repo.ui.configlist('merge', 'preferancestor') == ['*']:
1633 cahs = repo.changelog.commonancestorsheads(p1.node(), p2.node())
1661 cahs = repo.changelog.commonancestorsheads(p1.node(), p2.node())
1634 pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
1662 pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
1635 else:
1663 else:
1636 pas = [p1.ancestor(p2, warn=branchmerge)]
1664 pas = [p1.ancestor(p2, warn=branchmerge)]
1637
1665
1638 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
1666 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
1639
1667
1640 ### check phase
1668 ### check phase
1641 if not overwrite:
1669 if not overwrite:
1642 if len(pl) > 1:
1670 if len(pl) > 1:
1643 raise error.Abort(_("outstanding uncommitted merge"))
1671 raise error.Abort(_("outstanding uncommitted merge"))
1644 ms = mergestate.read(repo)
1672 ms = mergestate.read(repo)
1645 if list(ms.unresolved()):
1673 if list(ms.unresolved()):
1646 raise error.Abort(_("outstanding merge conflicts"))
1674 raise error.Abort(_("outstanding merge conflicts"))
1647 if branchmerge:
1675 if branchmerge:
1648 if pas == [p2]:
1676 if pas == [p2]:
1649 raise error.Abort(_("merging with a working directory ancestor"
1677 raise error.Abort(_("merging with a working directory ancestor"
1650 " has no effect"))
1678 " has no effect"))
1651 elif pas == [p1]:
1679 elif pas == [p1]:
1652 if not mergeancestor and wc.branch() == p2.branch():
1680 if not mergeancestor and wc.branch() == p2.branch():
1653 raise error.Abort(_("nothing to merge"),
1681 raise error.Abort(_("nothing to merge"),
1654 hint=_("use 'hg update' "
1682 hint=_("use 'hg update' "
1655 "or check 'hg heads'"))
1683 "or check 'hg heads'"))
1656 if not force and (wc.files() or wc.deleted()):
1684 if not force and (wc.files() or wc.deleted()):
1657 raise error.Abort(_("uncommitted changes"),
1685 raise error.Abort(_("uncommitted changes"),
1658 hint=_("use 'hg status' to list changes"))
1686 hint=_("use 'hg status' to list changes"))
1659 for s in sorted(wc.substate):
1687 for s in sorted(wc.substate):
1660 wc.sub(s).bailifchanged()
1688 wc.sub(s).bailifchanged()
1661
1689
1662 elif not overwrite:
1690 elif not overwrite:
1663 if p1 == p2: # no-op update
1691 if p1 == p2: # no-op update
1664 # call the hooks and exit early
1692 # call the hooks and exit early
1665 repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
1693 repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
1666 repo.hook('update', parent1=xp2, parent2='', error=0)
1694 repo.hook('update', parent1=xp2, parent2='', error=0)
1667 return 0, 0, 0, 0
1695 return 0, 0, 0, 0
1668
1696
1669 if (updatecheck == 'linear' and
1697 if (updatecheck == 'linear' and
1670 pas not in ([p1], [p2])): # nonlinear
1698 pas not in ([p1], [p2])): # nonlinear
1671 dirty = wc.dirty(missing=True)
1699 dirty = wc.dirty(missing=True)
1672 if dirty:
1700 if dirty:
1673 # Branching is a bit strange to ensure we do the minimal
1701 # Branching is a bit strange to ensure we do the minimal
1674 # amount of call to obsutil.foreground.
1702 # amount of call to obsutil.foreground.
1675 foreground = obsutil.foreground(repo, [p1.node()])
1703 foreground = obsutil.foreground(repo, [p1.node()])
1676 # note: the <node> variable contains a random identifier
1704 # note: the <node> variable contains a random identifier
1677 if repo[node].node() in foreground:
1705 if repo[node].node() in foreground:
1678 pass # allow updating to successors
1706 pass # allow updating to successors
1679 else:
1707 else:
1680 msg = _("uncommitted changes")
1708 msg = _("uncommitted changes")
1681 hint = _("commit or update --clean to discard changes")
1709 hint = _("commit or update --clean to discard changes")
1682 raise error.UpdateAbort(msg, hint=hint)
1710 raise error.UpdateAbort(msg, hint=hint)
1683 else:
1711 else:
1684 # Allow jumping branches if clean and specific rev given
1712 # Allow jumping branches if clean and specific rev given
1685 pass
1713 pass
1686
1714
1687 if overwrite:
1715 if overwrite:
1688 pas = [wc]
1716 pas = [wc]
1689 elif not branchmerge:
1717 elif not branchmerge:
1690 pas = [p1]
1718 pas = [p1]
1691
1719
1692 # deprecated config: merge.followcopies
1720 # deprecated config: merge.followcopies
1693 followcopies = repo.ui.configbool('merge', 'followcopies')
1721 followcopies = repo.ui.configbool('merge', 'followcopies')
1694 if overwrite:
1722 if overwrite:
1695 followcopies = False
1723 followcopies = False
1696 elif not pas[0]:
1724 elif not pas[0]:
1697 followcopies = False
1725 followcopies = False
1698 if not branchmerge and not wc.dirty(missing=True):
1726 if not branchmerge and not wc.dirty(missing=True):
1699 followcopies = False
1727 followcopies = False
1700
1728
1701 ### calculate phase
1729 ### calculate phase
1702 actionbyfile, diverge, renamedelete = calculateupdates(
1730 actionbyfile, diverge, renamedelete = calculateupdates(
1703 repo, wc, p2, pas, branchmerge, force, mergeancestor,
1731 repo, wc, p2, pas, branchmerge, force, mergeancestor,
1704 followcopies, matcher=matcher, mergeforce=mergeforce)
1732 followcopies, matcher=matcher, mergeforce=mergeforce)
1705
1733
1706 if updatecheck == 'noconflict':
1734 if updatecheck == 'noconflict':
1707 for f, (m, args, msg) in actionbyfile.iteritems():
1735 for f, (m, args, msg) in actionbyfile.iteritems():
1708 if m not in ('g', 'k', 'e', 'r', 'pr'):
1736 if m not in ('g', 'k', 'e', 'r', 'pr'):
1709 msg = _("conflicting changes")
1737 msg = _("conflicting changes")
1710 hint = _("commit or update --clean to discard changes")
1738 hint = _("commit or update --clean to discard changes")
1711 raise error.Abort(msg, hint=hint)
1739 raise error.Abort(msg, hint=hint)
1712
1740
1713 # Prompt and create actions. Most of this is in the resolve phase
1741 # Prompt and create actions. Most of this is in the resolve phase
1714 # already, but we can't handle .hgsubstate in filemerge or
1742 # already, but we can't handle .hgsubstate in filemerge or
1715 # subrepo.submerge yet so we have to keep prompting for it.
1743 # subrepo.submerge yet so we have to keep prompting for it.
1716 if '.hgsubstate' in actionbyfile:
1744 if '.hgsubstate' in actionbyfile:
1717 f = '.hgsubstate'
1745 f = '.hgsubstate'
1718 m, args, msg = actionbyfile[f]
1746 m, args, msg = actionbyfile[f]
1719 prompts = filemerge.partextras(labels)
1747 prompts = filemerge.partextras(labels)
1720 prompts['f'] = f
1748 prompts['f'] = f
1721 if m == 'cd':
1749 if m == 'cd':
1722 if repo.ui.promptchoice(
1750 if repo.ui.promptchoice(
1723 _("local%(l)s changed %(f)s which other%(o)s deleted\n"
1751 _("local%(l)s changed %(f)s which other%(o)s deleted\n"
1724 "use (c)hanged version or (d)elete?"
1752 "use (c)hanged version or (d)elete?"
1725 "$$ &Changed $$ &Delete") % prompts, 0):
1753 "$$ &Changed $$ &Delete") % prompts, 0):
1726 actionbyfile[f] = ('r', None, "prompt delete")
1754 actionbyfile[f] = ('r', None, "prompt delete")
1727 elif f in p1:
1755 elif f in p1:
1728 actionbyfile[f] = ('am', None, "prompt keep")
1756 actionbyfile[f] = ('am', None, "prompt keep")
1729 else:
1757 else:
1730 actionbyfile[f] = ('a', None, "prompt keep")
1758 actionbyfile[f] = ('a', None, "prompt keep")
1731 elif m == 'dc':
1759 elif m == 'dc':
1732 f1, f2, fa, move, anc = args
1760 f1, f2, fa, move, anc = args
1733 flags = p2[f2].flags()
1761 flags = p2[f2].flags()
1734 if repo.ui.promptchoice(
1762 if repo.ui.promptchoice(
1735 _("other%(o)s changed %(f)s which local%(l)s deleted\n"
1763 _("other%(o)s changed %(f)s which local%(l)s deleted\n"
1736 "use (c)hanged version or leave (d)eleted?"
1764 "use (c)hanged version or leave (d)eleted?"
1737 "$$ &Changed $$ &Deleted") % prompts, 0) == 0:
1765 "$$ &Changed $$ &Deleted") % prompts, 0) == 0:
1738 actionbyfile[f] = ('g', (flags, False), "prompt recreating")
1766 actionbyfile[f] = ('g', (flags, False), "prompt recreating")
1739 else:
1767 else:
1740 del actionbyfile[f]
1768 del actionbyfile[f]
1741
1769
1742 # Convert to dictionary-of-lists format
1770 # Convert to dictionary-of-lists format
1743 actions = dict((m, [])
1771 actions = dict((m, [])
1744 for m in 'a am f g cd dc r dm dg m e k p pr'.split())
1772 for m in 'a am f g cd dc r dm dg m e k p pr'.split())
1745 for f, (m, args, msg) in actionbyfile.iteritems():
1773 for f, (m, args, msg) in actionbyfile.iteritems():
1746 if m not in actions:
1774 if m not in actions:
1747 actions[m] = []
1775 actions[m] = []
1748 actions[m].append((f, args, msg))
1776 actions[m].append((f, args, msg))
1749
1777
1750 if not util.fscasesensitive(repo.path):
1778 if not util.fscasesensitive(repo.path):
1751 # check collision between files only in p2 for clean update
1779 # check collision between files only in p2 for clean update
1752 if (not branchmerge and
1780 if (not branchmerge and
1753 (force or not wc.dirty(missing=True, branch=False))):
1781 (force or not wc.dirty(missing=True, branch=False))):
1754 _checkcollision(repo, p2.manifest(), None)
1782 _checkcollision(repo, p2.manifest(), None)
1755 else:
1783 else:
1756 _checkcollision(repo, wc.manifest(), actions)
1784 _checkcollision(repo, wc.manifest(), actions)
1757
1785
1758 # divergent renames
1786 # divergent renames
1759 for f, fl in sorted(diverge.iteritems()):
1787 for f, fl in sorted(diverge.iteritems()):
1760 repo.ui.warn(_("note: possible conflict - %s was renamed "
1788 repo.ui.warn(_("note: possible conflict - %s was renamed "
1761 "multiple times to:\n") % f)
1789 "multiple times to:\n") % f)
1762 for nf in fl:
1790 for nf in fl:
1763 repo.ui.warn(" %s\n" % nf)
1791 repo.ui.warn(" %s\n" % nf)
1764
1792
1765 # rename and delete
1793 # rename and delete
1766 for f, fl in sorted(renamedelete.iteritems()):
1794 for f, fl in sorted(renamedelete.iteritems()):
1767 repo.ui.warn(_("note: possible conflict - %s was deleted "
1795 repo.ui.warn(_("note: possible conflict - %s was deleted "
1768 "and renamed to:\n") % f)
1796 "and renamed to:\n") % f)
1769 for nf in fl:
1797 for nf in fl:
1770 repo.ui.warn(" %s\n" % nf)
1798 repo.ui.warn(" %s\n" % nf)
1771
1799
1772 ### apply phase
1800 ### apply phase
1773 if not branchmerge: # just jump to the new rev
1801 if not branchmerge: # just jump to the new rev
1774 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
1802 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
1775 if not partial:
1803 if not partial:
1776 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
1804 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
1777 # note that we're in the middle of an update
1805 # note that we're in the middle of an update
1778 repo.vfs.write('updatestate', p2.hex())
1806 repo.vfs.write('updatestate', p2.hex())
1779
1807
1780 stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels)
1808 stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels)
1781 wc.flushall()
1809 wc.flushall()
1782
1810
1783 if not partial:
1811 if not partial:
1784 with repo.dirstate.parentchange():
1812 with repo.dirstate.parentchange():
1785 repo.setparents(fp1, fp2)
1813 repo.setparents(fp1, fp2)
1786 recordupdates(repo, actions, branchmerge)
1814 recordupdates(repo, actions, branchmerge)
1787 # update completed, clear state
1815 # update completed, clear state
1788 util.unlink(repo.vfs.join('updatestate'))
1816 util.unlink(repo.vfs.join('updatestate'))
1789
1817
1790 if not branchmerge:
1818 if not branchmerge:
1791 repo.dirstate.setbranch(p2.branch())
1819 repo.dirstate.setbranch(p2.branch())
1792
1820
1793 # If we're updating to a location, clean up any stale temporary includes
1821 # If we're updating to a location, clean up any stale temporary includes
1794 # (ex: this happens during hg rebase --abort).
1822 # (ex: this happens during hg rebase --abort).
1795 if not branchmerge:
1823 if not branchmerge:
1796 sparse.prunetemporaryincludes(repo)
1824 sparse.prunetemporaryincludes(repo)
1797
1825
1798 if not partial:
1826 if not partial:
1799 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
1827 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
1800 return stats
1828 return stats
1801
1829
1802 def graft(repo, ctx, pctx, labels, keepparent=False):
1830 def graft(repo, ctx, pctx, labels, keepparent=False):
1803 """Do a graft-like merge.
1831 """Do a graft-like merge.
1804
1832
1805 This is a merge where the merge ancestor is chosen such that one
1833 This is a merge where the merge ancestor is chosen such that one
1806 or more changesets are grafted onto the current changeset. In
1834 or more changesets are grafted onto the current changeset. In
1807 addition to the merge, this fixes up the dirstate to include only
1835 addition to the merge, this fixes up the dirstate to include only
1808 a single parent (if keepparent is False) and tries to duplicate any
1836 a single parent (if keepparent is False) and tries to duplicate any
1809 renames/copies appropriately.
1837 renames/copies appropriately.
1810
1838
1811 ctx - changeset to rebase
1839 ctx - changeset to rebase
1812 pctx - merge base, usually ctx.p1()
1840 pctx - merge base, usually ctx.p1()
1813 labels - merge labels eg ['local', 'graft']
1841 labels - merge labels eg ['local', 'graft']
1814 keepparent - keep second parent if any
1842 keepparent - keep second parent if any
1815
1843
1816 """
1844 """
1817 # If we're grafting a descendant onto an ancestor, be sure to pass
1845 # If we're grafting a descendant onto an ancestor, be sure to pass
1818 # mergeancestor=True to update. This does two things: 1) allows the merge if
1846 # mergeancestor=True to update. This does two things: 1) allows the merge if
1819 # the destination is the same as the parent of the ctx (so we can use graft
1847 # the destination is the same as the parent of the ctx (so we can use graft
1820 # to copy commits), and 2) informs update that the incoming changes are
1848 # to copy commits), and 2) informs update that the incoming changes are
1821 # newer than the destination so it doesn't prompt about "remote changed foo
1849 # newer than the destination so it doesn't prompt about "remote changed foo
1822 # which local deleted".
1850 # which local deleted".
1823 mergeancestor = repo.changelog.isancestor(repo['.'].node(), ctx.node())
1851 mergeancestor = repo.changelog.isancestor(repo['.'].node(), ctx.node())
1824
1852
1825 stats = update(repo, ctx.node(), True, True, pctx.node(),
1853 stats = update(repo, ctx.node(), True, True, pctx.node(),
1826 mergeancestor=mergeancestor, labels=labels)
1854 mergeancestor=mergeancestor, labels=labels)
1827
1855
1828 pother = nullid
1856 pother = nullid
1829 parents = ctx.parents()
1857 parents = ctx.parents()
1830 if keepparent and len(parents) == 2 and pctx in parents:
1858 if keepparent and len(parents) == 2 and pctx in parents:
1831 parents.remove(pctx)
1859 parents.remove(pctx)
1832 pother = parents[0].node()
1860 pother = parents[0].node()
1833
1861
1834 with repo.dirstate.parentchange():
1862 with repo.dirstate.parentchange():
1835 repo.setparents(repo['.'].node(), pother)
1863 repo.setparents(repo['.'].node(), pother)
1836 repo.dirstate.write(repo.currenttransaction())
1864 repo.dirstate.write(repo.currenttransaction())
1837 # fix up dirstate for copies and renames
1865 # fix up dirstate for copies and renames
1838 copies.duplicatecopies(repo, ctx.rev(), pctx.rev())
1866 copies.duplicatecopies(repo, ctx.rev(), pctx.rev())
1839 return stats
1867 return stats
General Comments 0
You need to be logged in to leave comments. Login now