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