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