##// END OF EJS Templates
merge: mark .hgsubstate as possibly dirty before submerge for consistency...
FUJIWARA Katsunori -
r23971:6becb9db stable
parent child Browse files
Show More
@@ -1,1189 +1,1199 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 import struct
8 import struct
9
9
10 from node import nullid, nullrev, hex, bin
10 from node import nullid, nullrev, hex, bin
11 from i18n import _
11 from i18n import _
12 from mercurial import obsolete
12 from mercurial import obsolete
13 import error as errormod, util, filemerge, copies, subrepo, worker
13 import error as errormod, util, filemerge, copies, subrepo, worker
14 import errno, os, shutil
14 import errno, os, shutil
15
15
16 _pack = struct.pack
16 _pack = struct.pack
17 _unpack = struct.unpack
17 _unpack = struct.unpack
18
18
19 def _droponode(data):
19 def _droponode(data):
20 # used for compatibility for v1
20 # used for compatibility for v1
21 bits = data.split('\0')
21 bits = data.split('\0')
22 bits = bits[:-2] + bits[-1:]
22 bits = bits[:-2] + bits[-1:]
23 return '\0'.join(bits)
23 return '\0'.join(bits)
24
24
25 class mergestate(object):
25 class mergestate(object):
26 '''track 3-way merge state of individual files
26 '''track 3-way merge state of individual files
27
27
28 it is stored on disk when needed. Two file are used, one with an old
28 it is stored on disk when needed. Two file are used, one with an old
29 format, one with a new format. Both contains similar data, but the new
29 format, one with a new format. Both contains similar data, but the new
30 format can store new kind of field.
30 format can store new kind of field.
31
31
32 Current new format is a list of arbitrary record of the form:
32 Current new format is a list of arbitrary record of the form:
33
33
34 [type][length][content]
34 [type][length][content]
35
35
36 Type is a single character, length is a 4 bytes integer, content is an
36 Type is a single character, length is a 4 bytes integer, content is an
37 arbitrary suites of bytes of length `length`.
37 arbitrary suites of bytes of length `length`.
38
38
39 Type should be a letter. Capital letter are mandatory record, Mercurial
39 Type should be a letter. Capital letter are mandatory record, Mercurial
40 should abort if they are unknown. lower case record can be safely ignored.
40 should abort if they are unknown. lower case record can be safely ignored.
41
41
42 Currently known record:
42 Currently known record:
43
43
44 L: the node of the "local" part of the merge (hexified version)
44 L: the node of the "local" part of the merge (hexified version)
45 O: the node of the "other" part of the merge (hexified version)
45 O: the node of the "other" part of the merge (hexified version)
46 F: a file to be merged entry
46 F: a file to be merged entry
47 '''
47 '''
48 statepathv1 = 'merge/state'
48 statepathv1 = 'merge/state'
49 statepathv2 = 'merge/state2'
49 statepathv2 = 'merge/state2'
50
50
51 def __init__(self, repo):
51 def __init__(self, repo):
52 self._repo = repo
52 self._repo = repo
53 self._dirty = False
53 self._dirty = False
54 self._read()
54 self._read()
55
55
56 def reset(self, node=None, other=None):
56 def reset(self, node=None, other=None):
57 self._state = {}
57 self._state = {}
58 self._local = None
58 self._local = None
59 self._other = None
59 self._other = None
60 if node:
60 if node:
61 self._local = node
61 self._local = node
62 self._other = other
62 self._other = other
63 shutil.rmtree(self._repo.join('merge'), True)
63 shutil.rmtree(self._repo.join('merge'), True)
64 self._dirty = False
64 self._dirty = False
65
65
66 def _read(self):
66 def _read(self):
67 """Analyse each record content to restore a serialized state from disk
67 """Analyse each record content to restore a serialized state from disk
68
68
69 This function process "record" entry produced by the de-serialization
69 This function process "record" entry produced by the de-serialization
70 of on disk file.
70 of on disk file.
71 """
71 """
72 self._state = {}
72 self._state = {}
73 self._local = None
73 self._local = None
74 self._other = None
74 self._other = None
75 records = self._readrecords()
75 records = self._readrecords()
76 for rtype, record in records:
76 for rtype, record in records:
77 if rtype == 'L':
77 if rtype == 'L':
78 self._local = bin(record)
78 self._local = bin(record)
79 elif rtype == 'O':
79 elif rtype == 'O':
80 self._other = bin(record)
80 self._other = bin(record)
81 elif rtype == 'F':
81 elif rtype == 'F':
82 bits = record.split('\0')
82 bits = record.split('\0')
83 self._state[bits[0]] = bits[1:]
83 self._state[bits[0]] = bits[1:]
84 elif not rtype.islower():
84 elif not rtype.islower():
85 raise util.Abort(_('unsupported merge state record: %s')
85 raise util.Abort(_('unsupported merge state record: %s')
86 % rtype)
86 % rtype)
87 self._dirty = False
87 self._dirty = False
88
88
89 def _readrecords(self):
89 def _readrecords(self):
90 """Read merge state from disk and return a list of record (TYPE, data)
90 """Read merge state from disk and return a list of record (TYPE, data)
91
91
92 We read data from both v1 and v2 files and decide which one to use.
92 We read data from both v1 and v2 files and decide which one to use.
93
93
94 V1 has been used by version prior to 2.9.1 and contains less data than
94 V1 has been used by version prior to 2.9.1 and contains less data than
95 v2. We read both versions and check if no data in v2 contradicts
95 v2. We read both versions and check if no data in v2 contradicts
96 v1. If there is not contradiction we can safely assume that both v1
96 v1. If there is not contradiction we can safely assume that both v1
97 and v2 were written at the same time and use the extract data in v2. If
97 and v2 were written at the same time and use the extract data in v2. If
98 there is contradiction we ignore v2 content as we assume an old version
98 there is contradiction we ignore v2 content as we assume an old version
99 of Mercurial has overwritten the mergestate file and left an old v2
99 of Mercurial has overwritten the mergestate file and left an old v2
100 file around.
100 file around.
101
101
102 returns list of record [(TYPE, data), ...]"""
102 returns list of record [(TYPE, data), ...]"""
103 v1records = self._readrecordsv1()
103 v1records = self._readrecordsv1()
104 v2records = self._readrecordsv2()
104 v2records = self._readrecordsv2()
105 oldv2 = set() # old format version of v2 record
105 oldv2 = set() # old format version of v2 record
106 for rec in v2records:
106 for rec in v2records:
107 if rec[0] == 'L':
107 if rec[0] == 'L':
108 oldv2.add(rec)
108 oldv2.add(rec)
109 elif rec[0] == 'F':
109 elif rec[0] == 'F':
110 # drop the onode data (not contained in v1)
110 # drop the onode data (not contained in v1)
111 oldv2.add(('F', _droponode(rec[1])))
111 oldv2.add(('F', _droponode(rec[1])))
112 for rec in v1records:
112 for rec in v1records:
113 if rec not in oldv2:
113 if rec not in oldv2:
114 # v1 file is newer than v2 file, use it
114 # v1 file is newer than v2 file, use it
115 # we have to infer the "other" changeset of the merge
115 # we have to infer the "other" changeset of the merge
116 # we cannot do better than that with v1 of the format
116 # we cannot do better than that with v1 of the format
117 mctx = self._repo[None].parents()[-1]
117 mctx = self._repo[None].parents()[-1]
118 v1records.append(('O', mctx.hex()))
118 v1records.append(('O', mctx.hex()))
119 # add place holder "other" file node information
119 # add place holder "other" file node information
120 # nobody is using it yet so we do no need to fetch the data
120 # nobody is using it yet so we do no need to fetch the data
121 # if mctx was wrong `mctx[bits[-2]]` may fails.
121 # if mctx was wrong `mctx[bits[-2]]` may fails.
122 for idx, r in enumerate(v1records):
122 for idx, r in enumerate(v1records):
123 if r[0] == 'F':
123 if r[0] == 'F':
124 bits = r[1].split('\0')
124 bits = r[1].split('\0')
125 bits.insert(-2, '')
125 bits.insert(-2, '')
126 v1records[idx] = (r[0], '\0'.join(bits))
126 v1records[idx] = (r[0], '\0'.join(bits))
127 return v1records
127 return v1records
128 else:
128 else:
129 return v2records
129 return v2records
130
130
131 def _readrecordsv1(self):
131 def _readrecordsv1(self):
132 """read on disk merge state for version 1 file
132 """read on disk merge state for version 1 file
133
133
134 returns list of record [(TYPE, data), ...]
134 returns list of record [(TYPE, data), ...]
135
135
136 Note: the "F" data from this file are one entry short
136 Note: the "F" data from this file are one entry short
137 (no "other file node" entry)
137 (no "other file node" entry)
138 """
138 """
139 records = []
139 records = []
140 try:
140 try:
141 f = self._repo.vfs(self.statepathv1)
141 f = self._repo.vfs(self.statepathv1)
142 for i, l in enumerate(f):
142 for i, l in enumerate(f):
143 if i == 0:
143 if i == 0:
144 records.append(('L', l[:-1]))
144 records.append(('L', l[:-1]))
145 else:
145 else:
146 records.append(('F', l[:-1]))
146 records.append(('F', l[:-1]))
147 f.close()
147 f.close()
148 except IOError, err:
148 except IOError, err:
149 if err.errno != errno.ENOENT:
149 if err.errno != errno.ENOENT:
150 raise
150 raise
151 return records
151 return records
152
152
153 def _readrecordsv2(self):
153 def _readrecordsv2(self):
154 """read on disk merge state for version 2 file
154 """read on disk merge state for version 2 file
155
155
156 returns list of record [(TYPE, data), ...]
156 returns list of record [(TYPE, data), ...]
157 """
157 """
158 records = []
158 records = []
159 try:
159 try:
160 f = self._repo.vfs(self.statepathv2)
160 f = self._repo.vfs(self.statepathv2)
161 data = f.read()
161 data = f.read()
162 off = 0
162 off = 0
163 end = len(data)
163 end = len(data)
164 while off < end:
164 while off < end:
165 rtype = data[off]
165 rtype = data[off]
166 off += 1
166 off += 1
167 length = _unpack('>I', data[off:(off + 4)])[0]
167 length = _unpack('>I', data[off:(off + 4)])[0]
168 off += 4
168 off += 4
169 record = data[off:(off + length)]
169 record = data[off:(off + length)]
170 off += length
170 off += length
171 records.append((rtype, record))
171 records.append((rtype, record))
172 f.close()
172 f.close()
173 except IOError, err:
173 except IOError, err:
174 if err.errno != errno.ENOENT:
174 if err.errno != errno.ENOENT:
175 raise
175 raise
176 return records
176 return records
177
177
178 def active(self):
178 def active(self):
179 """Whether mergestate is active.
179 """Whether mergestate is active.
180
180
181 Returns True if there appears to be mergestate. This is a rough proxy
181 Returns True if there appears to be mergestate. This is a rough proxy
182 for "is a merge in progress."
182 for "is a merge in progress."
183 """
183 """
184 # Check local variables before looking at filesystem for performance
184 # Check local variables before looking at filesystem for performance
185 # reasons.
185 # reasons.
186 return bool(self._local) or bool(self._state) or \
186 return bool(self._local) or bool(self._state) or \
187 self._repo.vfs.exists(self.statepathv1) or \
187 self._repo.vfs.exists(self.statepathv1) or \
188 self._repo.vfs.exists(self.statepathv2)
188 self._repo.vfs.exists(self.statepathv2)
189
189
190 def commit(self):
190 def commit(self):
191 """Write current state on disk (if necessary)"""
191 """Write current state on disk (if necessary)"""
192 if self._dirty:
192 if self._dirty:
193 records = []
193 records = []
194 records.append(('L', hex(self._local)))
194 records.append(('L', hex(self._local)))
195 records.append(('O', hex(self._other)))
195 records.append(('O', hex(self._other)))
196 for d, v in self._state.iteritems():
196 for d, v in self._state.iteritems():
197 records.append(('F', '\0'.join([d] + v)))
197 records.append(('F', '\0'.join([d] + v)))
198 self._writerecords(records)
198 self._writerecords(records)
199 self._dirty = False
199 self._dirty = False
200
200
201 def _writerecords(self, records):
201 def _writerecords(self, records):
202 """Write current state on disk (both v1 and v2)"""
202 """Write current state on disk (both v1 and v2)"""
203 self._writerecordsv1(records)
203 self._writerecordsv1(records)
204 self._writerecordsv2(records)
204 self._writerecordsv2(records)
205
205
206 def _writerecordsv1(self, records):
206 def _writerecordsv1(self, records):
207 """Write current state on disk in a version 1 file"""
207 """Write current state on disk in a version 1 file"""
208 f = self._repo.vfs(self.statepathv1, 'w')
208 f = self._repo.vfs(self.statepathv1, 'w')
209 irecords = iter(records)
209 irecords = iter(records)
210 lrecords = irecords.next()
210 lrecords = irecords.next()
211 assert lrecords[0] == 'L'
211 assert lrecords[0] == 'L'
212 f.write(hex(self._local) + '\n')
212 f.write(hex(self._local) + '\n')
213 for rtype, data in irecords:
213 for rtype, data in irecords:
214 if rtype == 'F':
214 if rtype == 'F':
215 f.write('%s\n' % _droponode(data))
215 f.write('%s\n' % _droponode(data))
216 f.close()
216 f.close()
217
217
218 def _writerecordsv2(self, records):
218 def _writerecordsv2(self, records):
219 """Write current state on disk in a version 2 file"""
219 """Write current state on disk in a version 2 file"""
220 f = self._repo.vfs(self.statepathv2, 'w')
220 f = self._repo.vfs(self.statepathv2, 'w')
221 for key, data in records:
221 for key, data in records:
222 assert len(key) == 1
222 assert len(key) == 1
223 format = '>sI%is' % len(data)
223 format = '>sI%is' % len(data)
224 f.write(_pack(format, key, len(data), data))
224 f.write(_pack(format, key, len(data), data))
225 f.close()
225 f.close()
226
226
227 def add(self, fcl, fco, fca, fd):
227 def add(self, fcl, fco, fca, fd):
228 """add a new (potentially?) conflicting file the merge state
228 """add a new (potentially?) conflicting file the merge state
229 fcl: file context for local,
229 fcl: file context for local,
230 fco: file context for remote,
230 fco: file context for remote,
231 fca: file context for ancestors,
231 fca: file context for ancestors,
232 fd: file path of the resulting merge.
232 fd: file path of the resulting merge.
233
233
234 note: also write the local version to the `.hg/merge` directory.
234 note: also write the local version to the `.hg/merge` directory.
235 """
235 """
236 hash = util.sha1(fcl.path()).hexdigest()
236 hash = util.sha1(fcl.path()).hexdigest()
237 self._repo.vfs.write('merge/' + hash, fcl.data())
237 self._repo.vfs.write('merge/' + hash, fcl.data())
238 self._state[fd] = ['u', hash, fcl.path(),
238 self._state[fd] = ['u', hash, fcl.path(),
239 fca.path(), hex(fca.filenode()),
239 fca.path(), hex(fca.filenode()),
240 fco.path(), hex(fco.filenode()),
240 fco.path(), hex(fco.filenode()),
241 fcl.flags()]
241 fcl.flags()]
242 self._dirty = True
242 self._dirty = True
243
243
244 def __contains__(self, dfile):
244 def __contains__(self, dfile):
245 return dfile in self._state
245 return dfile in self._state
246
246
247 def __getitem__(self, dfile):
247 def __getitem__(self, dfile):
248 return self._state[dfile][0]
248 return self._state[dfile][0]
249
249
250 def __iter__(self):
250 def __iter__(self):
251 return iter(sorted(self._state))
251 return iter(sorted(self._state))
252
252
253 def files(self):
253 def files(self):
254 return self._state.keys()
254 return self._state.keys()
255
255
256 def mark(self, dfile, state):
256 def mark(self, dfile, state):
257 self._state[dfile][0] = state
257 self._state[dfile][0] = state
258 self._dirty = True
258 self._dirty = True
259
259
260 def unresolved(self):
260 def unresolved(self):
261 """Obtain the paths of unresolved files."""
261 """Obtain the paths of unresolved files."""
262
262
263 for f, entry in self._state.items():
263 for f, entry in self._state.items():
264 if entry[0] == 'u':
264 if entry[0] == 'u':
265 yield f
265 yield f
266
266
267 def resolve(self, dfile, wctx, labels=None):
267 def resolve(self, dfile, wctx, labels=None):
268 """rerun merge process for file path `dfile`"""
268 """rerun merge process for file path `dfile`"""
269 if self[dfile] == 'r':
269 if self[dfile] == 'r':
270 return 0
270 return 0
271 stateentry = self._state[dfile]
271 stateentry = self._state[dfile]
272 state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
272 state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
273 octx = self._repo[self._other]
273 octx = self._repo[self._other]
274 fcd = wctx[dfile]
274 fcd = wctx[dfile]
275 fco = octx[ofile]
275 fco = octx[ofile]
276 fca = self._repo.filectx(afile, fileid=anode)
276 fca = self._repo.filectx(afile, fileid=anode)
277 # "premerge" x flags
277 # "premerge" x flags
278 flo = fco.flags()
278 flo = fco.flags()
279 fla = fca.flags()
279 fla = fca.flags()
280 if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
280 if 'x' in flags + flo + fla and 'l' not in flags + flo + fla:
281 if fca.node() == nullid:
281 if fca.node() == nullid:
282 self._repo.ui.warn(_('warning: cannot merge flags for %s\n') %
282 self._repo.ui.warn(_('warning: cannot merge flags for %s\n') %
283 afile)
283 afile)
284 elif flags == fla:
284 elif flags == fla:
285 flags = flo
285 flags = flo
286 # restore local
286 # restore local
287 f = self._repo.vfs('merge/' + hash)
287 f = self._repo.vfs('merge/' + hash)
288 self._repo.wwrite(dfile, f.read(), flags)
288 self._repo.wwrite(dfile, f.read(), flags)
289 f.close()
289 f.close()
290 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca,
290 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca,
291 labels=labels)
291 labels=labels)
292 if r is None:
292 if r is None:
293 # no real conflict
293 # no real conflict
294 del self._state[dfile]
294 del self._state[dfile]
295 self._dirty = True
295 self._dirty = True
296 elif not r:
296 elif not r:
297 self.mark(dfile, 'r')
297 self.mark(dfile, 'r')
298 return r
298 return r
299
299
300 def _checkunknownfile(repo, wctx, mctx, f, f2=None):
300 def _checkunknownfile(repo, wctx, mctx, f, f2=None):
301 if f2 is None:
301 if f2 is None:
302 f2 = f
302 f2 = f
303 return (os.path.isfile(repo.wjoin(f))
303 return (os.path.isfile(repo.wjoin(f))
304 and repo.wvfs.audit.check(f)
304 and repo.wvfs.audit.check(f)
305 and repo.dirstate.normalize(f) not in repo.dirstate
305 and repo.dirstate.normalize(f) not in repo.dirstate
306 and mctx[f2].cmp(wctx[f]))
306 and mctx[f2].cmp(wctx[f]))
307
307
308 def _checkunknownfiles(repo, wctx, mctx, force, actions):
308 def _checkunknownfiles(repo, wctx, mctx, force, actions):
309 """
309 """
310 Considers any actions that care about the presence of conflicting unknown
310 Considers any actions that care about the presence of conflicting unknown
311 files. For some actions, the result is to abort; for others, it is to
311 files. For some actions, the result is to abort; for others, it is to
312 choose a different action.
312 choose a different action.
313 """
313 """
314 aborts = []
314 aborts = []
315 if not force:
315 if not force:
316 for f, (m, args, msg) in actions.iteritems():
316 for f, (m, args, msg) in actions.iteritems():
317 if m in ('c', 'dc'):
317 if m in ('c', 'dc'):
318 if _checkunknownfile(repo, wctx, mctx, f):
318 if _checkunknownfile(repo, wctx, mctx, f):
319 aborts.append(f)
319 aborts.append(f)
320 elif m == 'dg':
320 elif m == 'dg':
321 if _checkunknownfile(repo, wctx, mctx, f, args[0]):
321 if _checkunknownfile(repo, wctx, mctx, f, args[0]):
322 aborts.append(f)
322 aborts.append(f)
323
323
324 for f in sorted(aborts):
324 for f in sorted(aborts):
325 repo.ui.warn(_("%s: untracked file differs\n") % f)
325 repo.ui.warn(_("%s: untracked file differs\n") % f)
326 if aborts:
326 if aborts:
327 raise util.Abort(_("untracked files in working directory differ "
327 raise util.Abort(_("untracked files in working directory differ "
328 "from files in requested revision"))
328 "from files in requested revision"))
329
329
330 for f, (m, args, msg) in actions.iteritems():
330 for f, (m, args, msg) in actions.iteritems():
331 if m == 'c':
331 if m == 'c':
332 actions[f] = ('g', args, msg)
332 actions[f] = ('g', args, msg)
333 elif m == 'cm':
333 elif m == 'cm':
334 fl2, anc = args
334 fl2, anc = args
335 different = _checkunknownfile(repo, wctx, mctx, f)
335 different = _checkunknownfile(repo, wctx, mctx, f)
336 if different:
336 if different:
337 actions[f] = ('m', (f, f, None, False, anc),
337 actions[f] = ('m', (f, f, None, False, anc),
338 "remote differs from untracked local")
338 "remote differs from untracked local")
339 else:
339 else:
340 actions[f] = ('g', (fl2,), "remote created")
340 actions[f] = ('g', (fl2,), "remote created")
341
341
342 def _forgetremoved(wctx, mctx, branchmerge):
342 def _forgetremoved(wctx, mctx, branchmerge):
343 """
343 """
344 Forget removed files
344 Forget removed files
345
345
346 If we're jumping between revisions (as opposed to merging), and if
346 If we're jumping between revisions (as opposed to merging), and if
347 neither the working directory nor the target rev has the file,
347 neither the working directory nor the target rev has the file,
348 then we need to remove it from the dirstate, to prevent the
348 then we need to remove it from the dirstate, to prevent the
349 dirstate from listing the file when it is no longer in the
349 dirstate from listing the file when it is no longer in the
350 manifest.
350 manifest.
351
351
352 If we're merging, and the other revision has removed a file
352 If we're merging, and the other revision has removed a file
353 that is not present in the working directory, we need to mark it
353 that is not present in the working directory, we need to mark it
354 as removed.
354 as removed.
355 """
355 """
356
356
357 actions = {}
357 actions = {}
358 m = 'f'
358 m = 'f'
359 if branchmerge:
359 if branchmerge:
360 m = 'r'
360 m = 'r'
361 for f in wctx.deleted():
361 for f in wctx.deleted():
362 if f not in mctx:
362 if f not in mctx:
363 actions[f] = m, None, "forget deleted"
363 actions[f] = m, None, "forget deleted"
364
364
365 if not branchmerge:
365 if not branchmerge:
366 for f in wctx.removed():
366 for f in wctx.removed():
367 if f not in mctx:
367 if f not in mctx:
368 actions[f] = 'f', None, "forget removed"
368 actions[f] = 'f', None, "forget removed"
369
369
370 return actions
370 return actions
371
371
372 def _checkcollision(repo, wmf, actions):
372 def _checkcollision(repo, wmf, actions):
373 # build provisional merged manifest up
373 # build provisional merged manifest up
374 pmmf = set(wmf)
374 pmmf = set(wmf)
375
375
376 if actions:
376 if actions:
377 # k, dr, e and rd are no-op
377 # k, dr, e and rd are no-op
378 for m in 'a', 'f', 'g', 'cd', 'dc':
378 for m in 'a', 'f', 'g', 'cd', 'dc':
379 for f, args, msg in actions[m]:
379 for f, args, msg in actions[m]:
380 pmmf.add(f)
380 pmmf.add(f)
381 for f, args, msg in actions['r']:
381 for f, args, msg in actions['r']:
382 pmmf.discard(f)
382 pmmf.discard(f)
383 for f, args, msg in actions['dm']:
383 for f, args, msg in actions['dm']:
384 f2, flags = args
384 f2, flags = args
385 pmmf.discard(f2)
385 pmmf.discard(f2)
386 pmmf.add(f)
386 pmmf.add(f)
387 for f, args, msg in actions['dg']:
387 for f, args, msg in actions['dg']:
388 pmmf.add(f)
388 pmmf.add(f)
389 for f, args, msg in actions['m']:
389 for f, args, msg in actions['m']:
390 f1, f2, fa, move, anc = args
390 f1, f2, fa, move, anc = args
391 if move:
391 if move:
392 pmmf.discard(f1)
392 pmmf.discard(f1)
393 pmmf.add(f)
393 pmmf.add(f)
394
394
395 # check case-folding collision in provisional merged manifest
395 # check case-folding collision in provisional merged manifest
396 foldmap = {}
396 foldmap = {}
397 for f in sorted(pmmf):
397 for f in sorted(pmmf):
398 fold = util.normcase(f)
398 fold = util.normcase(f)
399 if fold in foldmap:
399 if fold in foldmap:
400 raise util.Abort(_("case-folding collision between %s and %s")
400 raise util.Abort(_("case-folding collision between %s and %s")
401 % (f, foldmap[fold]))
401 % (f, foldmap[fold]))
402 foldmap[fold] = f
402 foldmap[fold] = f
403
403
404 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, partial,
404 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, partial,
405 acceptremote, followcopies):
405 acceptremote, followcopies):
406 """
406 """
407 Merge p1 and p2 with ancestor pa and generate merge action list
407 Merge p1 and p2 with ancestor pa and generate merge action list
408
408
409 branchmerge and force are as passed in to update
409 branchmerge and force are as passed in to update
410 partial = function to filter file lists
410 partial = function to filter file lists
411 acceptremote = accept the incoming changes without prompting
411 acceptremote = accept the incoming changes without prompting
412 """
412 """
413
413
414 copy, movewithdir, diverge, renamedelete = {}, {}, {}, {}
414 copy, movewithdir, diverge, renamedelete = {}, {}, {}, {}
415
415
416 # manifests fetched in order are going to be faster, so prime the caches
416 # manifests fetched in order are going to be faster, so prime the caches
417 [x.manifest() for x in
417 [x.manifest() for x in
418 sorted(wctx.parents() + [p2, pa], key=lambda x: x.rev())]
418 sorted(wctx.parents() + [p2, pa], key=lambda x: x.rev())]
419
419
420 if followcopies:
420 if followcopies:
421 ret = copies.mergecopies(repo, wctx, p2, pa)
421 ret = copies.mergecopies(repo, wctx, p2, pa)
422 copy, movewithdir, diverge, renamedelete = ret
422 copy, movewithdir, diverge, renamedelete = ret
423
423
424 repo.ui.note(_("resolving manifests\n"))
424 repo.ui.note(_("resolving manifests\n"))
425 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
425 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
426 % (bool(branchmerge), bool(force), bool(partial)))
426 % (bool(branchmerge), bool(force), bool(partial)))
427 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
427 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
428
428
429 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
429 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
430 copied = set(copy.values())
430 copied = set(copy.values())
431 copied.update(movewithdir.values())
431 copied.update(movewithdir.values())
432
432
433 if '.hgsubstate' in m1:
433 if '.hgsubstate' in m1:
434 # check whether sub state is modified
434 # check whether sub state is modified
435 for s in sorted(wctx.substate):
435 for s in sorted(wctx.substate):
436 if wctx.sub(s).dirty():
436 if wctx.sub(s).dirty():
437 m1['.hgsubstate'] += '+'
437 m1['.hgsubstate'] += '+'
438 break
438 break
439
439
440 # Compare manifests
440 # Compare manifests
441 diff = m1.diff(m2)
441 diff = m1.diff(m2)
442
442
443 actions = {}
443 actions = {}
444 for f, ((n1, fl1), (n2, fl2)) in diff.iteritems():
444 for f, ((n1, fl1), (n2, fl2)) in diff.iteritems():
445 if partial and not partial(f):
445 if partial and not partial(f):
446 continue
446 continue
447 if n1 and n2: # file exists on both local and remote side
447 if n1 and n2: # file exists on both local and remote side
448 if f not in ma:
448 if f not in ma:
449 fa = copy.get(f, None)
449 fa = copy.get(f, None)
450 if fa is not None:
450 if fa is not None:
451 actions[f] = ('m', (f, f, fa, False, pa.node()),
451 actions[f] = ('m', (f, f, fa, False, pa.node()),
452 "both renamed from " + fa)
452 "both renamed from " + fa)
453 else:
453 else:
454 actions[f] = ('m', (f, f, None, False, pa.node()),
454 actions[f] = ('m', (f, f, None, False, pa.node()),
455 "both created")
455 "both created")
456 else:
456 else:
457 a = ma[f]
457 a = ma[f]
458 fla = ma.flags(f)
458 fla = ma.flags(f)
459 nol = 'l' not in fl1 + fl2 + fla
459 nol = 'l' not in fl1 + fl2 + fla
460 if n2 == a and fl2 == fla:
460 if n2 == a and fl2 == fla:
461 actions[f] = ('k' , (), "remote unchanged")
461 actions[f] = ('k' , (), "remote unchanged")
462 elif n1 == a and fl1 == fla: # local unchanged - use remote
462 elif n1 == a and fl1 == fla: # local unchanged - use remote
463 if n1 == n2: # optimization: keep local content
463 if n1 == n2: # optimization: keep local content
464 actions[f] = ('e', (fl2,), "update permissions")
464 actions[f] = ('e', (fl2,), "update permissions")
465 else:
465 else:
466 actions[f] = ('g', (fl2,), "remote is newer")
466 actions[f] = ('g', (fl2,), "remote is newer")
467 elif nol and n2 == a: # remote only changed 'x'
467 elif nol and n2 == a: # remote only changed 'x'
468 actions[f] = ('e', (fl2,), "update permissions")
468 actions[f] = ('e', (fl2,), "update permissions")
469 elif nol and n1 == a: # local only changed 'x'
469 elif nol and n1 == a: # local only changed 'x'
470 actions[f] = ('g', (fl1,), "remote is newer")
470 actions[f] = ('g', (fl1,), "remote is newer")
471 else: # both changed something
471 else: # both changed something
472 actions[f] = ('m', (f, f, f, False, pa.node()),
472 actions[f] = ('m', (f, f, f, False, pa.node()),
473 "versions differ")
473 "versions differ")
474 elif n1: # file exists only on local side
474 elif n1: # file exists only on local side
475 if f in copied:
475 if f in copied:
476 pass # we'll deal with it on m2 side
476 pass # we'll deal with it on m2 side
477 elif f in movewithdir: # directory rename, move local
477 elif f in movewithdir: # directory rename, move local
478 f2 = movewithdir[f]
478 f2 = movewithdir[f]
479 if f2 in m2:
479 if f2 in m2:
480 actions[f2] = ('m', (f, f2, None, True, pa.node()),
480 actions[f2] = ('m', (f, f2, None, True, pa.node()),
481 "remote directory rename, both created")
481 "remote directory rename, both created")
482 else:
482 else:
483 actions[f2] = ('dm', (f, fl1),
483 actions[f2] = ('dm', (f, fl1),
484 "remote directory rename - move from " + f)
484 "remote directory rename - move from " + f)
485 elif f in copy:
485 elif f in copy:
486 f2 = copy[f]
486 f2 = copy[f]
487 actions[f] = ('m', (f, f2, f2, False, pa.node()),
487 actions[f] = ('m', (f, f2, f2, False, pa.node()),
488 "local copied/moved from " + f2)
488 "local copied/moved from " + f2)
489 elif f in ma: # clean, a different, no remote
489 elif f in ma: # clean, a different, no remote
490 if n1 != ma[f]:
490 if n1 != ma[f]:
491 if acceptremote:
491 if acceptremote:
492 actions[f] = ('r', None, "remote delete")
492 actions[f] = ('r', None, "remote delete")
493 else:
493 else:
494 actions[f] = ('cd', None, "prompt changed/deleted")
494 actions[f] = ('cd', None, "prompt changed/deleted")
495 elif n1[20:] == 'a':
495 elif n1[20:] == 'a':
496 # This extra 'a' is added by working copy manifest to mark
496 # This extra 'a' is added by working copy manifest to mark
497 # the file as locally added. We should forget it instead of
497 # the file as locally added. We should forget it instead of
498 # deleting it.
498 # deleting it.
499 actions[f] = ('f', None, "remote deleted")
499 actions[f] = ('f', None, "remote deleted")
500 else:
500 else:
501 actions[f] = ('r', None, "other deleted")
501 actions[f] = ('r', None, "other deleted")
502 elif n2: # file exists only on remote side
502 elif n2: # file exists only on remote side
503 if f in copied:
503 if f in copied:
504 pass # we'll deal with it on m1 side
504 pass # we'll deal with it on m1 side
505 elif f in movewithdir:
505 elif f in movewithdir:
506 f2 = movewithdir[f]
506 f2 = movewithdir[f]
507 if f2 in m1:
507 if f2 in m1:
508 actions[f2] = ('m', (f2, f, None, False, pa.node()),
508 actions[f2] = ('m', (f2, f, None, False, pa.node()),
509 "local directory rename, both created")
509 "local directory rename, both created")
510 else:
510 else:
511 actions[f2] = ('dg', (f, fl2),
511 actions[f2] = ('dg', (f, fl2),
512 "local directory rename - get from " + f)
512 "local directory rename - get from " + f)
513 elif f in copy:
513 elif f in copy:
514 f2 = copy[f]
514 f2 = copy[f]
515 if f2 in m2:
515 if f2 in m2:
516 actions[f] = ('m', (f2, f, f2, False, pa.node()),
516 actions[f] = ('m', (f2, f, f2, False, pa.node()),
517 "remote copied from " + f2)
517 "remote copied from " + f2)
518 else:
518 else:
519 actions[f] = ('m', (f2, f, f2, True, pa.node()),
519 actions[f] = ('m', (f2, f, f2, True, pa.node()),
520 "remote moved from " + f2)
520 "remote moved from " + f2)
521 elif f not in ma:
521 elif f not in ma:
522 # local unknown, remote created: the logic is described by the
522 # local unknown, remote created: the logic is described by the
523 # following table:
523 # following table:
524 #
524 #
525 # force branchmerge different | action
525 # force branchmerge different | action
526 # n * * | create
526 # n * * | create
527 # y n * | create
527 # y n * | create
528 # y y n | create
528 # y y n | create
529 # y y y | merge
529 # y y y | merge
530 #
530 #
531 # Checking whether the files are different is expensive, so we
531 # Checking whether the files are different is expensive, so we
532 # don't do that when we can avoid it.
532 # don't do that when we can avoid it.
533 if not force:
533 if not force:
534 actions[f] = ('c', (fl2,), "remote created")
534 actions[f] = ('c', (fl2,), "remote created")
535 elif not branchmerge:
535 elif not branchmerge:
536 actions[f] = ('c', (fl2,), "remote created")
536 actions[f] = ('c', (fl2,), "remote created")
537 else:
537 else:
538 actions[f] = ('cm', (fl2, pa.node()),
538 actions[f] = ('cm', (fl2, pa.node()),
539 "remote created, get or merge")
539 "remote created, get or merge")
540 elif n2 != ma[f]:
540 elif n2 != ma[f]:
541 if acceptremote:
541 if acceptremote:
542 actions[f] = ('c', (fl2,), "remote recreating")
542 actions[f] = ('c', (fl2,), "remote recreating")
543 else:
543 else:
544 actions[f] = ('dc', (fl2,), "prompt deleted/changed")
544 actions[f] = ('dc', (fl2,), "prompt deleted/changed")
545
545
546 return actions, diverge, renamedelete
546 return actions, diverge, renamedelete
547
547
548 def _resolvetrivial(repo, wctx, mctx, ancestor, actions):
548 def _resolvetrivial(repo, wctx, mctx, ancestor, actions):
549 """Resolves false conflicts where the nodeid changed but the content
549 """Resolves false conflicts where the nodeid changed but the content
550 remained the same."""
550 remained the same."""
551
551
552 for f, (m, args, msg) in actions.items():
552 for f, (m, args, msg) in actions.items():
553 if m == 'cd' and f in ancestor and not wctx[f].cmp(ancestor[f]):
553 if m == 'cd' and f in ancestor and not wctx[f].cmp(ancestor[f]):
554 # local did change but ended up with same content
554 # local did change but ended up with same content
555 actions[f] = 'r', None, "prompt same"
555 actions[f] = 'r', None, "prompt same"
556 elif m == 'dc' and f in ancestor and not mctx[f].cmp(ancestor[f]):
556 elif m == 'dc' and f in ancestor and not mctx[f].cmp(ancestor[f]):
557 # remote did change but ended up with same content
557 # remote did change but ended up with same content
558 del actions[f] # don't get = keep local deleted
558 del actions[f] # don't get = keep local deleted
559
559
560 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force, partial,
560 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force, partial,
561 acceptremote, followcopies):
561 acceptremote, followcopies):
562 "Calculate the actions needed to merge mctx into wctx using ancestors"
562 "Calculate the actions needed to merge mctx into wctx using ancestors"
563
563
564 if len(ancestors) == 1: # default
564 if len(ancestors) == 1: # default
565 actions, diverge, renamedelete = manifestmerge(
565 actions, diverge, renamedelete = manifestmerge(
566 repo, wctx, mctx, ancestors[0], branchmerge, force, partial,
566 repo, wctx, mctx, ancestors[0], branchmerge, force, partial,
567 acceptremote, followcopies)
567 acceptremote, followcopies)
568 _checkunknownfiles(repo, wctx, mctx, force, actions)
568 _checkunknownfiles(repo, wctx, mctx, force, actions)
569
569
570 else: # only when merge.preferancestor=* - the default
570 else: # only when merge.preferancestor=* - the default
571 repo.ui.note(
571 repo.ui.note(
572 _("note: merging %s and %s using bids from ancestors %s\n") %
572 _("note: merging %s and %s using bids from ancestors %s\n") %
573 (wctx, mctx, _(' and ').join(str(anc) for anc in ancestors)))
573 (wctx, mctx, _(' and ').join(str(anc) for anc in ancestors)))
574
574
575 # Call for bids
575 # Call for bids
576 fbids = {} # mapping filename to bids (action method to list af actions)
576 fbids = {} # mapping filename to bids (action method to list af actions)
577 diverge, renamedelete = None, None
577 diverge, renamedelete = None, None
578 for ancestor in ancestors:
578 for ancestor in ancestors:
579 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
579 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
580 actions, diverge1, renamedelete1 = manifestmerge(
580 actions, diverge1, renamedelete1 = manifestmerge(
581 repo, wctx, mctx, ancestor, branchmerge, force, partial,
581 repo, wctx, mctx, ancestor, branchmerge, force, partial,
582 acceptremote, followcopies)
582 acceptremote, followcopies)
583 _checkunknownfiles(repo, wctx, mctx, force, actions)
583 _checkunknownfiles(repo, wctx, mctx, force, actions)
584 if diverge is None: # and renamedelete is None.
584 if diverge is None: # and renamedelete is None.
585 # Arbitrarily pick warnings from first iteration
585 # Arbitrarily pick warnings from first iteration
586 diverge = diverge1
586 diverge = diverge1
587 renamedelete = renamedelete1
587 renamedelete = renamedelete1
588 for f, a in sorted(actions.iteritems()):
588 for f, a in sorted(actions.iteritems()):
589 m, args, msg = a
589 m, args, msg = a
590 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
590 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m))
591 if f in fbids:
591 if f in fbids:
592 d = fbids[f]
592 d = fbids[f]
593 if m in d:
593 if m in d:
594 d[m].append(a)
594 d[m].append(a)
595 else:
595 else:
596 d[m] = [a]
596 d[m] = [a]
597 else:
597 else:
598 fbids[f] = {m: [a]}
598 fbids[f] = {m: [a]}
599
599
600 # Pick the best bid for each file
600 # Pick the best bid for each file
601 repo.ui.note(_('\nauction for merging merge bids\n'))
601 repo.ui.note(_('\nauction for merging merge bids\n'))
602 actions = {}
602 actions = {}
603 for f, bids in sorted(fbids.items()):
603 for f, bids in sorted(fbids.items()):
604 # bids is a mapping from action method to list af actions
604 # bids is a mapping from action method to list af actions
605 # Consensus?
605 # Consensus?
606 if len(bids) == 1: # all bids are the same kind of method
606 if len(bids) == 1: # all bids are the same kind of method
607 m, l = bids.items()[0]
607 m, l = bids.items()[0]
608 if util.all(a == l[0] for a in l[1:]): # len(bids) is > 1
608 if util.all(a == l[0] for a in l[1:]): # len(bids) is > 1
609 repo.ui.note(" %s: consensus for %s\n" % (f, m))
609 repo.ui.note(" %s: consensus for %s\n" % (f, m))
610 actions[f] = l[0]
610 actions[f] = l[0]
611 continue
611 continue
612 # If keep is an option, just do it.
612 # If keep is an option, just do it.
613 if 'k' in bids:
613 if 'k' in bids:
614 repo.ui.note(" %s: picking 'keep' action\n" % f)
614 repo.ui.note(" %s: picking 'keep' action\n" % f)
615 actions[f] = bids['k'][0]
615 actions[f] = bids['k'][0]
616 continue
616 continue
617 # If there are gets and they all agree [how could they not?], do it.
617 # If there are gets and they all agree [how could they not?], do it.
618 if 'g' in bids:
618 if 'g' in bids:
619 ga0 = bids['g'][0]
619 ga0 = bids['g'][0]
620 if util.all(a == ga0 for a in bids['g'][1:]):
620 if util.all(a == ga0 for a in bids['g'][1:]):
621 repo.ui.note(" %s: picking 'get' action\n" % f)
621 repo.ui.note(" %s: picking 'get' action\n" % f)
622 actions[f] = ga0
622 actions[f] = ga0
623 continue
623 continue
624 # TODO: Consider other simple actions such as mode changes
624 # TODO: Consider other simple actions such as mode changes
625 # Handle inefficient democrazy.
625 # Handle inefficient democrazy.
626 repo.ui.note(_(' %s: multiple bids for merge action:\n') % f)
626 repo.ui.note(_(' %s: multiple bids for merge action:\n') % f)
627 for m, l in sorted(bids.items()):
627 for m, l in sorted(bids.items()):
628 for _f, args, msg in l:
628 for _f, args, msg in l:
629 repo.ui.note(' %s -> %s\n' % (msg, m))
629 repo.ui.note(' %s -> %s\n' % (msg, m))
630 # Pick random action. TODO: Instead, prompt user when resolving
630 # Pick random action. TODO: Instead, prompt user when resolving
631 m, l = bids.items()[0]
631 m, l = bids.items()[0]
632 repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
632 repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
633 (f, m))
633 (f, m))
634 actions[f] = l[0]
634 actions[f] = l[0]
635 continue
635 continue
636 repo.ui.note(_('end of auction\n\n'))
636 repo.ui.note(_('end of auction\n\n'))
637
637
638 _resolvetrivial(repo, wctx, mctx, ancestors[0], actions)
638 _resolvetrivial(repo, wctx, mctx, ancestors[0], actions)
639
639
640 if wctx.rev() is None:
640 if wctx.rev() is None:
641 fractions = _forgetremoved(wctx, mctx, branchmerge)
641 fractions = _forgetremoved(wctx, mctx, branchmerge)
642 actions.update(fractions)
642 actions.update(fractions)
643
643
644 return actions, diverge, renamedelete
644 return actions, diverge, renamedelete
645
645
646 def batchremove(repo, actions):
646 def batchremove(repo, actions):
647 """apply removes to the working directory
647 """apply removes to the working directory
648
648
649 yields tuples for progress updates
649 yields tuples for progress updates
650 """
650 """
651 verbose = repo.ui.verbose
651 verbose = repo.ui.verbose
652 unlink = util.unlinkpath
652 unlink = util.unlinkpath
653 wjoin = repo.wjoin
653 wjoin = repo.wjoin
654 audit = repo.wvfs.audit
654 audit = repo.wvfs.audit
655 i = 0
655 i = 0
656 for f, args, msg in actions:
656 for f, args, msg in actions:
657 repo.ui.debug(" %s: %s -> r\n" % (f, msg))
657 repo.ui.debug(" %s: %s -> r\n" % (f, msg))
658 if verbose:
658 if verbose:
659 repo.ui.note(_("removing %s\n") % f)
659 repo.ui.note(_("removing %s\n") % f)
660 audit(f)
660 audit(f)
661 try:
661 try:
662 unlink(wjoin(f), ignoremissing=True)
662 unlink(wjoin(f), ignoremissing=True)
663 except OSError, inst:
663 except OSError, inst:
664 repo.ui.warn(_("update failed to remove %s: %s!\n") %
664 repo.ui.warn(_("update failed to remove %s: %s!\n") %
665 (f, inst.strerror))
665 (f, inst.strerror))
666 if i == 100:
666 if i == 100:
667 yield i, f
667 yield i, f
668 i = 0
668 i = 0
669 i += 1
669 i += 1
670 if i > 0:
670 if i > 0:
671 yield i, f
671 yield i, f
672
672
673 def batchget(repo, mctx, actions):
673 def batchget(repo, mctx, actions):
674 """apply gets to the working directory
674 """apply gets to the working directory
675
675
676 mctx is the context to get from
676 mctx is the context to get from
677
677
678 yields tuples for progress updates
678 yields tuples for progress updates
679 """
679 """
680 verbose = repo.ui.verbose
680 verbose = repo.ui.verbose
681 fctx = mctx.filectx
681 fctx = mctx.filectx
682 wwrite = repo.wwrite
682 wwrite = repo.wwrite
683 i = 0
683 i = 0
684 for f, args, msg in actions:
684 for f, args, msg in actions:
685 repo.ui.debug(" %s: %s -> g\n" % (f, msg))
685 repo.ui.debug(" %s: %s -> g\n" % (f, msg))
686 if verbose:
686 if verbose:
687 repo.ui.note(_("getting %s\n") % f)
687 repo.ui.note(_("getting %s\n") % f)
688 wwrite(f, fctx(f).data(), args[0])
688 wwrite(f, fctx(f).data(), args[0])
689 if i == 100:
689 if i == 100:
690 yield i, f
690 yield i, f
691 i = 0
691 i = 0
692 i += 1
692 i += 1
693 if i > 0:
693 if i > 0:
694 yield i, f
694 yield i, f
695
695
696 def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None):
696 def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None):
697 """apply the merge action list to the working directory
697 """apply the merge action list to the working directory
698
698
699 wctx is the working copy context
699 wctx is the working copy context
700 mctx is the context to be merged into the working copy
700 mctx is the context to be merged into the working copy
701
701
702 Return a tuple of counts (updated, merged, removed, unresolved) that
702 Return a tuple of counts (updated, merged, removed, unresolved) that
703 describes how many files were affected by the update.
703 describes how many files were affected by the update.
704 """
704 """
705
705
706 updated, merged, removed, unresolved = 0, 0, 0, 0
706 updated, merged, removed, unresolved = 0, 0, 0, 0
707 ms = mergestate(repo)
707 ms = mergestate(repo)
708 ms.reset(wctx.p1().node(), mctx.node())
708 ms.reset(wctx.p1().node(), mctx.node())
709 moves = []
709 moves = []
710 for m, l in actions.items():
710 for m, l in actions.items():
711 l.sort()
711 l.sort()
712
712
713 # prescan for merges
713 # prescan for merges
714 for f, args, msg in actions['m']:
714 for f, args, msg in actions['m']:
715 f1, f2, fa, move, anc = args
715 f1, f2, fa, move, anc = args
716 if f == '.hgsubstate': # merged internally
716 if f == '.hgsubstate': # merged internally
717 continue
717 continue
718 repo.ui.debug(" preserving %s for resolve of %s\n" % (f1, f))
718 repo.ui.debug(" preserving %s for resolve of %s\n" % (f1, f))
719 fcl = wctx[f1]
719 fcl = wctx[f1]
720 fco = mctx[f2]
720 fco = mctx[f2]
721 actx = repo[anc]
721 actx = repo[anc]
722 if fa in actx:
722 if fa in actx:
723 fca = actx[fa]
723 fca = actx[fa]
724 else:
724 else:
725 fca = repo.filectx(f1, fileid=nullrev)
725 fca = repo.filectx(f1, fileid=nullrev)
726 ms.add(fcl, fco, fca, f)
726 ms.add(fcl, fco, fca, f)
727 if f1 != f and move:
727 if f1 != f and move:
728 moves.append(f1)
728 moves.append(f1)
729
729
730 audit = repo.wvfs.audit
730 audit = repo.wvfs.audit
731 _updating = _('updating')
731 _updating = _('updating')
732 _files = _('files')
732 _files = _('files')
733 progress = repo.ui.progress
733 progress = repo.ui.progress
734
734
735 # remove renamed files after safely stored
735 # remove renamed files after safely stored
736 for f in moves:
736 for f in moves:
737 if os.path.lexists(repo.wjoin(f)):
737 if os.path.lexists(repo.wjoin(f)):
738 repo.ui.debug("removing %s\n" % f)
738 repo.ui.debug("removing %s\n" % f)
739 audit(f)
739 audit(f)
740 util.unlinkpath(repo.wjoin(f))
740 util.unlinkpath(repo.wjoin(f))
741
741
742 numupdates = sum(len(l) for m, l in actions.items() if m != 'k')
742 numupdates = sum(len(l) for m, l in actions.items() if m != 'k')
743
743
744 def dirtysubstate():
745 # mark '.hgsubstate' as possibly dirty forcibly, because
746 # modified '.hgsubstate' is misunderstood as clean,
747 # when both st_size/st_mtime of '.hgsubstate' aren't changed,
748 # even if "submerge" fails and '.hgsubstate' is inconsistent
749 repo.dirstate.normallookup('.hgsubstate')
750
744 if [a for a in actions['r'] if a[0] == '.hgsubstate']:
751 if [a for a in actions['r'] if a[0] == '.hgsubstate']:
752 dirtysubstate()
745 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
753 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
746
754
747 # remove in parallel (must come first)
755 # remove in parallel (must come first)
748 z = 0
756 z = 0
749 prog = worker.worker(repo.ui, 0.001, batchremove, (repo,), actions['r'])
757 prog = worker.worker(repo.ui, 0.001, batchremove, (repo,), actions['r'])
750 for i, item in prog:
758 for i, item in prog:
751 z += i
759 z += i
752 progress(_updating, z, item=item, total=numupdates, unit=_files)
760 progress(_updating, z, item=item, total=numupdates, unit=_files)
753 removed = len(actions['r'])
761 removed = len(actions['r'])
754
762
755 # get in parallel
763 # get in parallel
756 prog = worker.worker(repo.ui, 0.001, batchget, (repo, mctx), actions['g'])
764 prog = worker.worker(repo.ui, 0.001, batchget, (repo, mctx), actions['g'])
757 for i, item in prog:
765 for i, item in prog:
758 z += i
766 z += i
759 progress(_updating, z, item=item, total=numupdates, unit=_files)
767 progress(_updating, z, item=item, total=numupdates, unit=_files)
760 updated = len(actions['g'])
768 updated = len(actions['g'])
761
769
762 if [a for a in actions['g'] if a[0] == '.hgsubstate']:
770 if [a for a in actions['g'] if a[0] == '.hgsubstate']:
771 dirtysubstate()
763 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
772 subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
764
773
765 # forget (manifest only, just log it) (must come first)
774 # forget (manifest only, just log it) (must come first)
766 for f, args, msg in actions['f']:
775 for f, args, msg in actions['f']:
767 repo.ui.debug(" %s: %s -> f\n" % (f, msg))
776 repo.ui.debug(" %s: %s -> f\n" % (f, msg))
768 z += 1
777 z += 1
769 progress(_updating, z, item=f, total=numupdates, unit=_files)
778 progress(_updating, z, item=f, total=numupdates, unit=_files)
770
779
771 # re-add (manifest only, just log it)
780 # re-add (manifest only, just log it)
772 for f, args, msg in actions['a']:
781 for f, args, msg in actions['a']:
773 repo.ui.debug(" %s: %s -> a\n" % (f, msg))
782 repo.ui.debug(" %s: %s -> a\n" % (f, msg))
774 z += 1
783 z += 1
775 progress(_updating, z, item=f, total=numupdates, unit=_files)
784 progress(_updating, z, item=f, total=numupdates, unit=_files)
776
785
777 # keep (noop, just log it)
786 # keep (noop, just log it)
778 for f, args, msg in actions['k']:
787 for f, args, msg in actions['k']:
779 repo.ui.debug(" %s: %s -> k\n" % (f, msg))
788 repo.ui.debug(" %s: %s -> k\n" % (f, msg))
780 # no progress
789 # no progress
781
790
782 # merge
791 # merge
783 for f, args, msg in actions['m']:
792 for f, args, msg in actions['m']:
784 repo.ui.debug(" %s: %s -> m\n" % (f, msg))
793 repo.ui.debug(" %s: %s -> m\n" % (f, msg))
785 z += 1
794 z += 1
786 progress(_updating, z, item=f, total=numupdates, unit=_files)
795 progress(_updating, z, item=f, total=numupdates, unit=_files)
787 if f == '.hgsubstate': # subrepo states need updating
796 if f == '.hgsubstate': # subrepo states need updating
797 dirtysubstate()
788 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
798 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
789 overwrite)
799 overwrite)
790 continue
800 continue
791 audit(f)
801 audit(f)
792 r = ms.resolve(f, wctx, labels=labels)
802 r = ms.resolve(f, wctx, labels=labels)
793 if r is not None and r > 0:
803 if r is not None and r > 0:
794 unresolved += 1
804 unresolved += 1
795 else:
805 else:
796 if r is None:
806 if r is None:
797 updated += 1
807 updated += 1
798 else:
808 else:
799 merged += 1
809 merged += 1
800
810
801 # directory rename, move local
811 # directory rename, move local
802 for f, args, msg in actions['dm']:
812 for f, args, msg in actions['dm']:
803 repo.ui.debug(" %s: %s -> dm\n" % (f, msg))
813 repo.ui.debug(" %s: %s -> dm\n" % (f, msg))
804 z += 1
814 z += 1
805 progress(_updating, z, item=f, total=numupdates, unit=_files)
815 progress(_updating, z, item=f, total=numupdates, unit=_files)
806 f0, flags = args
816 f0, flags = args
807 repo.ui.note(_("moving %s to %s\n") % (f0, f))
817 repo.ui.note(_("moving %s to %s\n") % (f0, f))
808 audit(f)
818 audit(f)
809 repo.wwrite(f, wctx.filectx(f0).data(), flags)
819 repo.wwrite(f, wctx.filectx(f0).data(), flags)
810 util.unlinkpath(repo.wjoin(f0))
820 util.unlinkpath(repo.wjoin(f0))
811 updated += 1
821 updated += 1
812
822
813 # local directory rename, get
823 # local directory rename, get
814 for f, args, msg in actions['dg']:
824 for f, args, msg in actions['dg']:
815 repo.ui.debug(" %s: %s -> dg\n" % (f, msg))
825 repo.ui.debug(" %s: %s -> dg\n" % (f, msg))
816 z += 1
826 z += 1
817 progress(_updating, z, item=f, total=numupdates, unit=_files)
827 progress(_updating, z, item=f, total=numupdates, unit=_files)
818 f0, flags = args
828 f0, flags = args
819 repo.ui.note(_("getting %s to %s\n") % (f0, f))
829 repo.ui.note(_("getting %s to %s\n") % (f0, f))
820 repo.wwrite(f, mctx.filectx(f0).data(), flags)
830 repo.wwrite(f, mctx.filectx(f0).data(), flags)
821 updated += 1
831 updated += 1
822
832
823 # exec
833 # exec
824 for f, args, msg in actions['e']:
834 for f, args, msg in actions['e']:
825 repo.ui.debug(" %s: %s -> e\n" % (f, msg))
835 repo.ui.debug(" %s: %s -> e\n" % (f, msg))
826 z += 1
836 z += 1
827 progress(_updating, z, item=f, total=numupdates, unit=_files)
837 progress(_updating, z, item=f, total=numupdates, unit=_files)
828 flags, = args
838 flags, = args
829 audit(f)
839 audit(f)
830 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
840 util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
831 updated += 1
841 updated += 1
832
842
833 ms.commit()
843 ms.commit()
834 progress(_updating, None, total=numupdates, unit=_files)
844 progress(_updating, None, total=numupdates, unit=_files)
835
845
836 return updated, merged, removed, unresolved
846 return updated, merged, removed, unresolved
837
847
838 def recordupdates(repo, actions, branchmerge):
848 def recordupdates(repo, actions, branchmerge):
839 "record merge actions to the dirstate"
849 "record merge actions to the dirstate"
840 # remove (must come first)
850 # remove (must come first)
841 for f, args, msg in actions['r']:
851 for f, args, msg in actions['r']:
842 if branchmerge:
852 if branchmerge:
843 repo.dirstate.remove(f)
853 repo.dirstate.remove(f)
844 else:
854 else:
845 repo.dirstate.drop(f)
855 repo.dirstate.drop(f)
846
856
847 # forget (must come first)
857 # forget (must come first)
848 for f, args, msg in actions['f']:
858 for f, args, msg in actions['f']:
849 repo.dirstate.drop(f)
859 repo.dirstate.drop(f)
850
860
851 # re-add
861 # re-add
852 for f, args, msg in actions['a']:
862 for f, args, msg in actions['a']:
853 if not branchmerge:
863 if not branchmerge:
854 repo.dirstate.add(f)
864 repo.dirstate.add(f)
855
865
856 # exec change
866 # exec change
857 for f, args, msg in actions['e']:
867 for f, args, msg in actions['e']:
858 repo.dirstate.normallookup(f)
868 repo.dirstate.normallookup(f)
859
869
860 # keep
870 # keep
861 for f, args, msg in actions['k']:
871 for f, args, msg in actions['k']:
862 pass
872 pass
863
873
864 # get
874 # get
865 for f, args, msg in actions['g']:
875 for f, args, msg in actions['g']:
866 if branchmerge:
876 if branchmerge:
867 repo.dirstate.otherparent(f)
877 repo.dirstate.otherparent(f)
868 else:
878 else:
869 repo.dirstate.normal(f)
879 repo.dirstate.normal(f)
870
880
871 # merge
881 # merge
872 for f, args, msg in actions['m']:
882 for f, args, msg in actions['m']:
873 f1, f2, fa, move, anc = args
883 f1, f2, fa, move, anc = args
874 if branchmerge:
884 if branchmerge:
875 # We've done a branch merge, mark this file as merged
885 # We've done a branch merge, mark this file as merged
876 # so that we properly record the merger later
886 # so that we properly record the merger later
877 repo.dirstate.merge(f)
887 repo.dirstate.merge(f)
878 if f1 != f2: # copy/rename
888 if f1 != f2: # copy/rename
879 if move:
889 if move:
880 repo.dirstate.remove(f1)
890 repo.dirstate.remove(f1)
881 if f1 != f:
891 if f1 != f:
882 repo.dirstate.copy(f1, f)
892 repo.dirstate.copy(f1, f)
883 else:
893 else:
884 repo.dirstate.copy(f2, f)
894 repo.dirstate.copy(f2, f)
885 else:
895 else:
886 # We've update-merged a locally modified file, so
896 # We've update-merged a locally modified file, so
887 # we set the dirstate to emulate a normal checkout
897 # we set the dirstate to emulate a normal checkout
888 # of that file some time in the past. Thus our
898 # of that file some time in the past. Thus our
889 # merge will appear as a normal local file
899 # merge will appear as a normal local file
890 # modification.
900 # modification.
891 if f2 == f: # file not locally copied/moved
901 if f2 == f: # file not locally copied/moved
892 repo.dirstate.normallookup(f)
902 repo.dirstate.normallookup(f)
893 if move:
903 if move:
894 repo.dirstate.drop(f1)
904 repo.dirstate.drop(f1)
895
905
896 # directory rename, move local
906 # directory rename, move local
897 for f, args, msg in actions['dm']:
907 for f, args, msg in actions['dm']:
898 f0, flag = args
908 f0, flag = args
899 if branchmerge:
909 if branchmerge:
900 repo.dirstate.add(f)
910 repo.dirstate.add(f)
901 repo.dirstate.remove(f0)
911 repo.dirstate.remove(f0)
902 repo.dirstate.copy(f0, f)
912 repo.dirstate.copy(f0, f)
903 else:
913 else:
904 repo.dirstate.normal(f)
914 repo.dirstate.normal(f)
905 repo.dirstate.drop(f0)
915 repo.dirstate.drop(f0)
906
916
907 # directory rename, get
917 # directory rename, get
908 for f, args, msg in actions['dg']:
918 for f, args, msg in actions['dg']:
909 f0, flag = args
919 f0, flag = args
910 if branchmerge:
920 if branchmerge:
911 repo.dirstate.add(f)
921 repo.dirstate.add(f)
912 repo.dirstate.copy(f0, f)
922 repo.dirstate.copy(f0, f)
913 else:
923 else:
914 repo.dirstate.normal(f)
924 repo.dirstate.normal(f)
915
925
916 def update(repo, node, branchmerge, force, partial, ancestor=None,
926 def update(repo, node, branchmerge, force, partial, ancestor=None,
917 mergeancestor=False, labels=None):
927 mergeancestor=False, labels=None):
918 """
928 """
919 Perform a merge between the working directory and the given node
929 Perform a merge between the working directory and the given node
920
930
921 node = the node to update to, or None if unspecified
931 node = the node to update to, or None if unspecified
922 branchmerge = whether to merge between branches
932 branchmerge = whether to merge between branches
923 force = whether to force branch merging or file overwriting
933 force = whether to force branch merging or file overwriting
924 partial = a function to filter file lists (dirstate not updated)
934 partial = a function to filter file lists (dirstate not updated)
925 mergeancestor = whether it is merging with an ancestor. If true,
935 mergeancestor = whether it is merging with an ancestor. If true,
926 we should accept the incoming changes for any prompts that occur.
936 we should accept the incoming changes for any prompts that occur.
927 If false, merging with an ancestor (fast-forward) is only allowed
937 If false, merging with an ancestor (fast-forward) is only allowed
928 between different named branches. This flag is used by rebase extension
938 between different named branches. This flag is used by rebase extension
929 as a temporary fix and should be avoided in general.
939 as a temporary fix and should be avoided in general.
930
940
931 The table below shows all the behaviors of the update command
941 The table below shows all the behaviors of the update command
932 given the -c and -C or no options, whether the working directory
942 given the -c and -C or no options, whether the working directory
933 is dirty, whether a revision is specified, and the relationship of
943 is dirty, whether a revision is specified, and the relationship of
934 the parent rev to the target rev (linear, on the same named
944 the parent rev to the target rev (linear, on the same named
935 branch, or on another named branch).
945 branch, or on another named branch).
936
946
937 This logic is tested by test-update-branches.t.
947 This logic is tested by test-update-branches.t.
938
948
939 -c -C dirty rev | linear same cross
949 -c -C dirty rev | linear same cross
940 n n n n | ok (1) x
950 n n n n | ok (1) x
941 n n n y | ok ok ok
951 n n n y | ok ok ok
942 n n y n | merge (2) (2)
952 n n y n | merge (2) (2)
943 n n y y | merge (3) (3)
953 n n y y | merge (3) (3)
944 n y * * | --- discard ---
954 n y * * | --- discard ---
945 y n y * | --- (4) ---
955 y n y * | --- (4) ---
946 y n n * | --- ok ---
956 y n n * | --- ok ---
947 y y * * | --- (5) ---
957 y y * * | --- (5) ---
948
958
949 x = can't happen
959 x = can't happen
950 * = don't-care
960 * = don't-care
951 1 = abort: not a linear update (merge or update --check to force update)
961 1 = abort: not a linear update (merge or update --check to force update)
952 2 = abort: uncommitted changes (commit and merge, or update --clean to
962 2 = abort: uncommitted changes (commit and merge, or update --clean to
953 discard changes)
963 discard changes)
954 3 = abort: uncommitted changes (commit or update --clean to discard changes)
964 3 = abort: uncommitted changes (commit or update --clean to discard changes)
955 4 = abort: uncommitted changes (checked in commands.py)
965 4 = abort: uncommitted changes (checked in commands.py)
956 5 = incompatible options (checked in commands.py)
966 5 = incompatible options (checked in commands.py)
957
967
958 Return the same tuple as applyupdates().
968 Return the same tuple as applyupdates().
959 """
969 """
960
970
961 onode = node
971 onode = node
962 wlock = repo.wlock()
972 wlock = repo.wlock()
963 try:
973 try:
964 wc = repo[None]
974 wc = repo[None]
965 pl = wc.parents()
975 pl = wc.parents()
966 p1 = pl[0]
976 p1 = pl[0]
967 pas = [None]
977 pas = [None]
968 if ancestor is not None:
978 if ancestor is not None:
969 pas = [repo[ancestor]]
979 pas = [repo[ancestor]]
970
980
971 if node is None:
981 if node is None:
972 # Here is where we should consider bookmarks, divergent bookmarks,
982 # Here is where we should consider bookmarks, divergent bookmarks,
973 # foreground changesets (successors), and tip of current branch;
983 # foreground changesets (successors), and tip of current branch;
974 # but currently we are only checking the branch tips.
984 # but currently we are only checking the branch tips.
975 try:
985 try:
976 node = repo.branchtip(wc.branch())
986 node = repo.branchtip(wc.branch())
977 except errormod.RepoLookupError:
987 except errormod.RepoLookupError:
978 if wc.branch() == 'default': # no default branch!
988 if wc.branch() == 'default': # no default branch!
979 node = repo.lookup('tip') # update to tip
989 node = repo.lookup('tip') # update to tip
980 else:
990 else:
981 raise util.Abort(_("branch %s not found") % wc.branch())
991 raise util.Abort(_("branch %s not found") % wc.branch())
982
992
983 if p1.obsolete() and not p1.children():
993 if p1.obsolete() and not p1.children():
984 # allow updating to successors
994 # allow updating to successors
985 successors = obsolete.successorssets(repo, p1.node())
995 successors = obsolete.successorssets(repo, p1.node())
986
996
987 # behavior of certain cases is as follows,
997 # behavior of certain cases is as follows,
988 #
998 #
989 # divergent changesets: update to highest rev, similar to what
999 # divergent changesets: update to highest rev, similar to what
990 # is currently done when there are more than one head
1000 # is currently done when there are more than one head
991 # (i.e. 'tip')
1001 # (i.e. 'tip')
992 #
1002 #
993 # replaced changesets: same as divergent except we know there
1003 # replaced changesets: same as divergent except we know there
994 # is no conflict
1004 # is no conflict
995 #
1005 #
996 # pruned changeset: no update is done; though, we could
1006 # pruned changeset: no update is done; though, we could
997 # consider updating to the first non-obsolete parent,
1007 # consider updating to the first non-obsolete parent,
998 # similar to what is current done for 'hg prune'
1008 # similar to what is current done for 'hg prune'
999
1009
1000 if successors:
1010 if successors:
1001 # flatten the list here handles both divergent (len > 1)
1011 # flatten the list here handles both divergent (len > 1)
1002 # and the usual case (len = 1)
1012 # and the usual case (len = 1)
1003 successors = [n for sub in successors for n in sub]
1013 successors = [n for sub in successors for n in sub]
1004
1014
1005 # get the max revision for the given successors set,
1015 # get the max revision for the given successors set,
1006 # i.e. the 'tip' of a set
1016 # i.e. the 'tip' of a set
1007 node = repo.revs('max(%ln)', successors).first()
1017 node = repo.revs('max(%ln)', successors).first()
1008 pas = [p1]
1018 pas = [p1]
1009
1019
1010 overwrite = force and not branchmerge
1020 overwrite = force and not branchmerge
1011
1021
1012 p2 = repo[node]
1022 p2 = repo[node]
1013 if pas[0] is None:
1023 if pas[0] is None:
1014 if repo.ui.config('merge', 'preferancestor', '*') == '*':
1024 if repo.ui.config('merge', 'preferancestor', '*') == '*':
1015 cahs = repo.changelog.commonancestorsheads(p1.node(), p2.node())
1025 cahs = repo.changelog.commonancestorsheads(p1.node(), p2.node())
1016 pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
1026 pas = [repo[anc] for anc in (sorted(cahs) or [nullid])]
1017 else:
1027 else:
1018 pas = [p1.ancestor(p2, warn=branchmerge)]
1028 pas = [p1.ancestor(p2, warn=branchmerge)]
1019
1029
1020 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
1030 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
1021
1031
1022 ### check phase
1032 ### check phase
1023 if not overwrite and len(pl) > 1:
1033 if not overwrite and len(pl) > 1:
1024 raise util.Abort(_("outstanding uncommitted merge"))
1034 raise util.Abort(_("outstanding uncommitted merge"))
1025 if branchmerge:
1035 if branchmerge:
1026 if pas == [p2]:
1036 if pas == [p2]:
1027 raise util.Abort(_("merging with a working directory ancestor"
1037 raise util.Abort(_("merging with a working directory ancestor"
1028 " has no effect"))
1038 " has no effect"))
1029 elif pas == [p1]:
1039 elif pas == [p1]:
1030 if not mergeancestor and p1.branch() == p2.branch():
1040 if not mergeancestor and p1.branch() == p2.branch():
1031 raise util.Abort(_("nothing to merge"),
1041 raise util.Abort(_("nothing to merge"),
1032 hint=_("use 'hg update' "
1042 hint=_("use 'hg update' "
1033 "or check 'hg heads'"))
1043 "or check 'hg heads'"))
1034 if not force and (wc.files() or wc.deleted()):
1044 if not force and (wc.files() or wc.deleted()):
1035 raise util.Abort(_("uncommitted changes"),
1045 raise util.Abort(_("uncommitted changes"),
1036 hint=_("use 'hg status' to list changes"))
1046 hint=_("use 'hg status' to list changes"))
1037 for s in sorted(wc.substate):
1047 for s in sorted(wc.substate):
1038 if wc.sub(s).dirty():
1048 if wc.sub(s).dirty():
1039 raise util.Abort(_("uncommitted changes in "
1049 raise util.Abort(_("uncommitted changes in "
1040 "subrepository '%s'") % s)
1050 "subrepository '%s'") % s)
1041
1051
1042 elif not overwrite:
1052 elif not overwrite:
1043 if p1 == p2: # no-op update
1053 if p1 == p2: # no-op update
1044 # call the hooks and exit early
1054 # call the hooks and exit early
1045 repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
1055 repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
1046 repo.hook('update', parent1=xp2, parent2='', error=0)
1056 repo.hook('update', parent1=xp2, parent2='', error=0)
1047 return 0, 0, 0, 0
1057 return 0, 0, 0, 0
1048
1058
1049 if pas not in ([p1], [p2]): # nonlinear
1059 if pas not in ([p1], [p2]): # nonlinear
1050 dirty = wc.dirty(missing=True)
1060 dirty = wc.dirty(missing=True)
1051 if dirty or onode is None:
1061 if dirty or onode is None:
1052 # Branching is a bit strange to ensure we do the minimal
1062 # Branching is a bit strange to ensure we do the minimal
1053 # amount of call to obsolete.background.
1063 # amount of call to obsolete.background.
1054 foreground = obsolete.foreground(repo, [p1.node()])
1064 foreground = obsolete.foreground(repo, [p1.node()])
1055 # note: the <node> variable contains a random identifier
1065 # note: the <node> variable contains a random identifier
1056 if repo[node].node() in foreground:
1066 if repo[node].node() in foreground:
1057 pas = [p1] # allow updating to successors
1067 pas = [p1] # allow updating to successors
1058 elif dirty:
1068 elif dirty:
1059 msg = _("uncommitted changes")
1069 msg = _("uncommitted changes")
1060 if onode is None:
1070 if onode is None:
1061 hint = _("commit and merge, or update --clean to"
1071 hint = _("commit and merge, or update --clean to"
1062 " discard changes")
1072 " discard changes")
1063 else:
1073 else:
1064 hint = _("commit or update --clean to discard"
1074 hint = _("commit or update --clean to discard"
1065 " changes")
1075 " changes")
1066 raise util.Abort(msg, hint=hint)
1076 raise util.Abort(msg, hint=hint)
1067 else: # node is none
1077 else: # node is none
1068 msg = _("not a linear update")
1078 msg = _("not a linear update")
1069 hint = _("merge or update --check to force update")
1079 hint = _("merge or update --check to force update")
1070 raise util.Abort(msg, hint=hint)
1080 raise util.Abort(msg, hint=hint)
1071 else:
1081 else:
1072 # Allow jumping branches if clean and specific rev given
1082 # Allow jumping branches if clean and specific rev given
1073 pas = [p1]
1083 pas = [p1]
1074
1084
1075 followcopies = False
1085 followcopies = False
1076 if overwrite:
1086 if overwrite:
1077 pas = [wc]
1087 pas = [wc]
1078 elif pas == [p2]: # backwards
1088 elif pas == [p2]: # backwards
1079 pas = [wc.p1()]
1089 pas = [wc.p1()]
1080 elif not branchmerge and not wc.dirty(missing=True):
1090 elif not branchmerge and not wc.dirty(missing=True):
1081 pass
1091 pass
1082 elif pas[0] and repo.ui.configbool('merge', 'followcopies', True):
1092 elif pas[0] and repo.ui.configbool('merge', 'followcopies', True):
1083 followcopies = True
1093 followcopies = True
1084
1094
1085 ### calculate phase
1095 ### calculate phase
1086 actionbyfile, diverge, renamedelete = calculateupdates(
1096 actionbyfile, diverge, renamedelete = calculateupdates(
1087 repo, wc, p2, pas, branchmerge, force, partial, mergeancestor,
1097 repo, wc, p2, pas, branchmerge, force, partial, mergeancestor,
1088 followcopies)
1098 followcopies)
1089 # Convert to dictionary-of-lists format
1099 # Convert to dictionary-of-lists format
1090 actions = dict((m, []) for m in 'a f g cd dc r dm dg m e k'.split())
1100 actions = dict((m, []) for m in 'a f g cd dc r dm dg m e k'.split())
1091 for f, (m, args, msg) in actionbyfile.iteritems():
1101 for f, (m, args, msg) in actionbyfile.iteritems():
1092 if m not in actions:
1102 if m not in actions:
1093 actions[m] = []
1103 actions[m] = []
1094 actions[m].append((f, args, msg))
1104 actions[m].append((f, args, msg))
1095
1105
1096 if not util.checkcase(repo.path):
1106 if not util.checkcase(repo.path):
1097 # check collision between files only in p2 for clean update
1107 # check collision between files only in p2 for clean update
1098 if (not branchmerge and
1108 if (not branchmerge and
1099 (force or not wc.dirty(missing=True, branch=False))):
1109 (force or not wc.dirty(missing=True, branch=False))):
1100 _checkcollision(repo, p2.manifest(), None)
1110 _checkcollision(repo, p2.manifest(), None)
1101 else:
1111 else:
1102 _checkcollision(repo, wc.manifest(), actions)
1112 _checkcollision(repo, wc.manifest(), actions)
1103
1113
1104 # Prompt and create actions. TODO: Move this towards resolve phase.
1114 # Prompt and create actions. TODO: Move this towards resolve phase.
1105 for f, args, msg in sorted(actions['cd']):
1115 for f, args, msg in sorted(actions['cd']):
1106 if repo.ui.promptchoice(
1116 if repo.ui.promptchoice(
1107 _("local changed %s which remote deleted\n"
1117 _("local changed %s which remote deleted\n"
1108 "use (c)hanged version or (d)elete?"
1118 "use (c)hanged version or (d)elete?"
1109 "$$ &Changed $$ &Delete") % f, 0):
1119 "$$ &Changed $$ &Delete") % f, 0):
1110 actions['r'].append((f, None, "prompt delete"))
1120 actions['r'].append((f, None, "prompt delete"))
1111 else:
1121 else:
1112 actions['a'].append((f, None, "prompt keep"))
1122 actions['a'].append((f, None, "prompt keep"))
1113 del actions['cd'][:]
1123 del actions['cd'][:]
1114
1124
1115 for f, args, msg in sorted(actions['dc']):
1125 for f, args, msg in sorted(actions['dc']):
1116 flags, = args
1126 flags, = args
1117 if repo.ui.promptchoice(
1127 if repo.ui.promptchoice(
1118 _("remote changed %s which local deleted\n"
1128 _("remote changed %s which local deleted\n"
1119 "use (c)hanged version or leave (d)eleted?"
1129 "use (c)hanged version or leave (d)eleted?"
1120 "$$ &Changed $$ &Deleted") % f, 0) == 0:
1130 "$$ &Changed $$ &Deleted") % f, 0) == 0:
1121 actions['g'].append((f, (flags,), "prompt recreating"))
1131 actions['g'].append((f, (flags,), "prompt recreating"))
1122 del actions['dc'][:]
1132 del actions['dc'][:]
1123
1133
1124 ### apply phase
1134 ### apply phase
1125 if not branchmerge: # just jump to the new rev
1135 if not branchmerge: # just jump to the new rev
1126 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
1136 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
1127 if not partial:
1137 if not partial:
1128 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
1138 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
1129 # note that we're in the middle of an update
1139 # note that we're in the middle of an update
1130 repo.vfs.write('updatestate', p2.hex())
1140 repo.vfs.write('updatestate', p2.hex())
1131
1141
1132 stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels)
1142 stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels)
1133
1143
1134 # divergent renames
1144 # divergent renames
1135 for f, fl in sorted(diverge.iteritems()):
1145 for f, fl in sorted(diverge.iteritems()):
1136 repo.ui.warn(_("note: possible conflict - %s was renamed "
1146 repo.ui.warn(_("note: possible conflict - %s was renamed "
1137 "multiple times to:\n") % f)
1147 "multiple times to:\n") % f)
1138 for nf in fl:
1148 for nf in fl:
1139 repo.ui.warn(" %s\n" % nf)
1149 repo.ui.warn(" %s\n" % nf)
1140
1150
1141 # rename and delete
1151 # rename and delete
1142 for f, fl in sorted(renamedelete.iteritems()):
1152 for f, fl in sorted(renamedelete.iteritems()):
1143 repo.ui.warn(_("note: possible conflict - %s was deleted "
1153 repo.ui.warn(_("note: possible conflict - %s was deleted "
1144 "and renamed to:\n") % f)
1154 "and renamed to:\n") % f)
1145 for nf in fl:
1155 for nf in fl:
1146 repo.ui.warn(" %s\n" % nf)
1156 repo.ui.warn(" %s\n" % nf)
1147
1157
1148 if not partial:
1158 if not partial:
1149 repo.dirstate.beginparentchange()
1159 repo.dirstate.beginparentchange()
1150 repo.setparents(fp1, fp2)
1160 repo.setparents(fp1, fp2)
1151 recordupdates(repo, actions, branchmerge)
1161 recordupdates(repo, actions, branchmerge)
1152 # update completed, clear state
1162 # update completed, clear state
1153 util.unlink(repo.join('updatestate'))
1163 util.unlink(repo.join('updatestate'))
1154
1164
1155 if not branchmerge:
1165 if not branchmerge:
1156 repo.dirstate.setbranch(p2.branch())
1166 repo.dirstate.setbranch(p2.branch())
1157 repo.dirstate.endparentchange()
1167 repo.dirstate.endparentchange()
1158 finally:
1168 finally:
1159 wlock.release()
1169 wlock.release()
1160
1170
1161 if not partial:
1171 if not partial:
1162 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
1172 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
1163 return stats
1173 return stats
1164
1174
1165 def graft(repo, ctx, pctx, labels):
1175 def graft(repo, ctx, pctx, labels):
1166 """Do a graft-like merge.
1176 """Do a graft-like merge.
1167
1177
1168 This is a merge where the merge ancestor is chosen such that one
1178 This is a merge where the merge ancestor is chosen such that one
1169 or more changesets are grafted onto the current changeset. In
1179 or more changesets are grafted onto the current changeset. In
1170 addition to the merge, this fixes up the dirstate to include only
1180 addition to the merge, this fixes up the dirstate to include only
1171 a single parent and tries to duplicate any renames/copies
1181 a single parent and tries to duplicate any renames/copies
1172 appropriately.
1182 appropriately.
1173
1183
1174 ctx - changeset to rebase
1184 ctx - changeset to rebase
1175 pctx - merge base, usually ctx.p1()
1185 pctx - merge base, usually ctx.p1()
1176 labels - merge labels eg ['local', 'graft']
1186 labels - merge labels eg ['local', 'graft']
1177
1187
1178 """
1188 """
1179
1189
1180 stats = update(repo, ctx.node(), True, True, False, pctx.node(),
1190 stats = update(repo, ctx.node(), True, True, False, pctx.node(),
1181 labels=labels)
1191 labels=labels)
1182 # drop the second merge parent
1192 # drop the second merge parent
1183 repo.dirstate.beginparentchange()
1193 repo.dirstate.beginparentchange()
1184 repo.setparents(repo['.'].node(), nullid)
1194 repo.setparents(repo['.'].node(), nullid)
1185 repo.dirstate.write()
1195 repo.dirstate.write()
1186 # fix up dirstate for copies and renames
1196 # fix up dirstate for copies and renames
1187 copies.duplicatecopies(repo, ctx.rev(), pctx.rev())
1197 copies.duplicatecopies(repo, ctx.rev(), pctx.rev())
1188 repo.dirstate.endparentchange()
1198 repo.dirstate.endparentchange()
1189 return stats
1199 return stats
@@ -1,1471 +1,1474 b''
1 Let commit recurse into subrepos by default to match pre-2.0 behavior:
1 Let commit recurse into subrepos by default to match pre-2.0 behavior:
2
2
3 $ echo "[ui]" >> $HGRCPATH
3 $ echo "[ui]" >> $HGRCPATH
4 $ echo "commitsubrepos = Yes" >> $HGRCPATH
4 $ echo "commitsubrepos = Yes" >> $HGRCPATH
5
5
6 $ hg init t
6 $ hg init t
7 $ cd t
7 $ cd t
8
8
9 first revision, no sub
9 first revision, no sub
10
10
11 $ echo a > a
11 $ echo a > a
12 $ hg ci -Am0
12 $ hg ci -Am0
13 adding a
13 adding a
14
14
15 add first sub
15 add first sub
16
16
17 $ echo s = s > .hgsub
17 $ echo s = s > .hgsub
18 $ hg add .hgsub
18 $ hg add .hgsub
19 $ hg init s
19 $ hg init s
20 $ echo a > s/a
20 $ echo a > s/a
21
21
22 Issue2232: committing a subrepo without .hgsub
22 Issue2232: committing a subrepo without .hgsub
23
23
24 $ hg ci -mbad s
24 $ hg ci -mbad s
25 abort: can't commit subrepos without .hgsub
25 abort: can't commit subrepos without .hgsub
26 [255]
26 [255]
27
27
28 $ hg -R s ci -Ams0
28 $ hg -R s ci -Ams0
29 adding a
29 adding a
30 $ hg sum
30 $ hg sum
31 parent: 0:f7b1eb17ad24 tip
31 parent: 0:f7b1eb17ad24 tip
32 0
32 0
33 branch: default
33 branch: default
34 commit: 1 added, 1 subrepos
34 commit: 1 added, 1 subrepos
35 update: (current)
35 update: (current)
36 $ hg ci -m1
36 $ hg ci -m1
37
37
38 test handling .hgsubstate "added" explicitly.
38 test handling .hgsubstate "added" explicitly.
39
39
40 $ hg parents --template '{node}\n{files}\n'
40 $ hg parents --template '{node}\n{files}\n'
41 7cf8cfea66e410e8e3336508dfeec07b3192de51
41 7cf8cfea66e410e8e3336508dfeec07b3192de51
42 .hgsub .hgsubstate
42 .hgsub .hgsubstate
43 $ hg rollback -q
43 $ hg rollback -q
44 $ hg add .hgsubstate
44 $ hg add .hgsubstate
45 $ hg ci -m1
45 $ hg ci -m1
46 $ hg parents --template '{node}\n{files}\n'
46 $ hg parents --template '{node}\n{files}\n'
47 7cf8cfea66e410e8e3336508dfeec07b3192de51
47 7cf8cfea66e410e8e3336508dfeec07b3192de51
48 .hgsub .hgsubstate
48 .hgsub .hgsubstate
49
49
50 Revert subrepo and test subrepo fileset keyword:
50 Revert subrepo and test subrepo fileset keyword:
51
51
52 $ echo b > s/a
52 $ echo b > s/a
53 $ hg revert "set:subrepo('glob:s*')"
53 $ hg revert "set:subrepo('glob:s*')"
54 reverting subrepo s
54 reverting subrepo s
55 reverting s/a (glob)
55 reverting s/a (glob)
56 $ rm s/a.orig
56 $ rm s/a.orig
57
57
58 Revert subrepo with no backup. The "reverting s/a" line is gone since
58 Revert subrepo with no backup. The "reverting s/a" line is gone since
59 we're really running 'hg update' in the subrepo:
59 we're really running 'hg update' in the subrepo:
60
60
61 $ echo b > s/a
61 $ echo b > s/a
62 $ hg revert --no-backup s
62 $ hg revert --no-backup s
63 reverting subrepo s
63 reverting subrepo s
64
64
65 Issue2022: update -C
65 Issue2022: update -C
66
66
67 $ echo b > s/a
67 $ echo b > s/a
68 $ hg sum
68 $ hg sum
69 parent: 1:7cf8cfea66e4 tip
69 parent: 1:7cf8cfea66e4 tip
70 1
70 1
71 branch: default
71 branch: default
72 commit: 1 subrepos
72 commit: 1 subrepos
73 update: (current)
73 update: (current)
74 $ hg co -C 1
74 $ hg co -C 1
75 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
75 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 $ hg sum
76 $ hg sum
77 parent: 1:7cf8cfea66e4 tip
77 parent: 1:7cf8cfea66e4 tip
78 1
78 1
79 branch: default
79 branch: default
80 commit: (clean)
80 commit: (clean)
81 update: (current)
81 update: (current)
82
82
83 commands that require a clean repo should respect subrepos
83 commands that require a clean repo should respect subrepos
84
84
85 $ echo b >> s/a
85 $ echo b >> s/a
86 $ hg backout tip
86 $ hg backout tip
87 abort: uncommitted changes in subrepo s
87 abort: uncommitted changes in subrepo s
88 [255]
88 [255]
89 $ hg revert -C -R s s/a
89 $ hg revert -C -R s s/a
90
90
91 add sub sub
91 add sub sub
92
92
93 $ echo ss = ss > s/.hgsub
93 $ echo ss = ss > s/.hgsub
94 $ hg init s/ss
94 $ hg init s/ss
95 $ echo a > s/ss/a
95 $ echo a > s/ss/a
96 $ hg -R s add s/.hgsub
96 $ hg -R s add s/.hgsub
97 $ hg -R s/ss add s/ss/a
97 $ hg -R s/ss add s/ss/a
98 $ hg sum
98 $ hg sum
99 parent: 1:7cf8cfea66e4 tip
99 parent: 1:7cf8cfea66e4 tip
100 1
100 1
101 branch: default
101 branch: default
102 commit: 1 subrepos
102 commit: 1 subrepos
103 update: (current)
103 update: (current)
104 $ hg ci -m2
104 $ hg ci -m2
105 committing subrepository s
105 committing subrepository s
106 committing subrepository s/ss (glob)
106 committing subrepository s/ss (glob)
107 $ hg sum
107 $ hg sum
108 parent: 2:df30734270ae tip
108 parent: 2:df30734270ae tip
109 2
109 2
110 branch: default
110 branch: default
111 commit: (clean)
111 commit: (clean)
112 update: (current)
112 update: (current)
113
113
114 test handling .hgsubstate "modified" explicitly.
114 test handling .hgsubstate "modified" explicitly.
115
115
116 $ hg parents --template '{node}\n{files}\n'
116 $ hg parents --template '{node}\n{files}\n'
117 df30734270ae757feb35e643b7018e818e78a9aa
117 df30734270ae757feb35e643b7018e818e78a9aa
118 .hgsubstate
118 .hgsubstate
119 $ hg rollback -q
119 $ hg rollback -q
120 $ hg status -A .hgsubstate
120 $ hg status -A .hgsubstate
121 M .hgsubstate
121 M .hgsubstate
122 $ hg ci -m2
122 $ hg ci -m2
123 $ hg parents --template '{node}\n{files}\n'
123 $ hg parents --template '{node}\n{files}\n'
124 df30734270ae757feb35e643b7018e818e78a9aa
124 df30734270ae757feb35e643b7018e818e78a9aa
125 .hgsubstate
125 .hgsubstate
126
126
127 bump sub rev (and check it is ignored by ui.commitsubrepos)
127 bump sub rev (and check it is ignored by ui.commitsubrepos)
128
128
129 $ echo b > s/a
129 $ echo b > s/a
130 $ hg -R s ci -ms1
130 $ hg -R s ci -ms1
131 $ hg --config ui.commitsubrepos=no ci -m3
131 $ hg --config ui.commitsubrepos=no ci -m3
132
132
133 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
133 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
134
134
135 $ echo c > s/a
135 $ echo c > s/a
136 $ hg --config ui.commitsubrepos=no ci -m4
136 $ hg --config ui.commitsubrepos=no ci -m4
137 abort: uncommitted changes in subrepo s
137 abort: uncommitted changes in subrepo s
138 (use --subrepos for recursive commit)
138 (use --subrepos for recursive commit)
139 [255]
139 [255]
140 $ hg id
140 $ hg id
141 f6affe3fbfaa+ tip
141 f6affe3fbfaa+ tip
142 $ hg -R s ci -mc
142 $ hg -R s ci -mc
143 $ hg id
143 $ hg id
144 f6affe3fbfaa+ tip
144 f6affe3fbfaa+ tip
145 $ echo d > s/a
145 $ echo d > s/a
146 $ hg ci -m4
146 $ hg ci -m4
147 committing subrepository s
147 committing subrepository s
148 $ hg tip -R s
148 $ hg tip -R s
149 changeset: 4:02dcf1d70411
149 changeset: 4:02dcf1d70411
150 tag: tip
150 tag: tip
151 user: test
151 user: test
152 date: Thu Jan 01 00:00:00 1970 +0000
152 date: Thu Jan 01 00:00:00 1970 +0000
153 summary: 4
153 summary: 4
154
154
155
155
156 check caching
156 check caching
157
157
158 $ hg co 0
158 $ hg co 0
159 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
159 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
160 $ hg debugsub
160 $ hg debugsub
161
161
162 restore
162 restore
163
163
164 $ hg co
164 $ hg co
165 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
165 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
166 $ hg debugsub
166 $ hg debugsub
167 path s
167 path s
168 source s
168 source s
169 revision 02dcf1d704118aee3ee306ccfa1910850d5b05ef
169 revision 02dcf1d704118aee3ee306ccfa1910850d5b05ef
170
170
171 new branch for merge tests
171 new branch for merge tests
172
172
173 $ hg co 1
173 $ hg co 1
174 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
174 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
175 $ echo t = t >> .hgsub
175 $ echo t = t >> .hgsub
176 $ hg init t
176 $ hg init t
177 $ echo t > t/t
177 $ echo t > t/t
178 $ hg -R t add t
178 $ hg -R t add t
179 adding t/t (glob)
179 adding t/t (glob)
180
180
181 5
181 5
182
182
183 $ hg ci -m5 # add sub
183 $ hg ci -m5 # add sub
184 committing subrepository t
184 committing subrepository t
185 created new head
185 created new head
186 $ echo t2 > t/t
186 $ echo t2 > t/t
187
187
188 6
188 6
189
189
190 $ hg st -R s
190 $ hg st -R s
191 $ hg ci -m6 # change sub
191 $ hg ci -m6 # change sub
192 committing subrepository t
192 committing subrepository t
193 $ hg debugsub
193 $ hg debugsub
194 path s
194 path s
195 source s
195 source s
196 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
196 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
197 path t
197 path t
198 source t
198 source t
199 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
199 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
200 $ echo t3 > t/t
200 $ echo t3 > t/t
201
201
202 7
202 7
203
203
204 $ hg ci -m7 # change sub again for conflict test
204 $ hg ci -m7 # change sub again for conflict test
205 committing subrepository t
205 committing subrepository t
206 $ hg rm .hgsub
206 $ hg rm .hgsub
207
207
208 8
208 8
209
209
210 $ hg ci -m8 # remove sub
210 $ hg ci -m8 # remove sub
211
211
212 test handling .hgsubstate "removed" explicitly.
212 test handling .hgsubstate "removed" explicitly.
213
213
214 $ hg parents --template '{node}\n{files}\n'
214 $ hg parents --template '{node}\n{files}\n'
215 96615c1dad2dc8e3796d7332c77ce69156f7b78e
215 96615c1dad2dc8e3796d7332c77ce69156f7b78e
216 .hgsub .hgsubstate
216 .hgsub .hgsubstate
217 $ hg rollback -q
217 $ hg rollback -q
218 $ hg remove .hgsubstate
218 $ hg remove .hgsubstate
219 $ hg ci -m8
219 $ hg ci -m8
220 $ hg parents --template '{node}\n{files}\n'
220 $ hg parents --template '{node}\n{files}\n'
221 96615c1dad2dc8e3796d7332c77ce69156f7b78e
221 96615c1dad2dc8e3796d7332c77ce69156f7b78e
222 .hgsub .hgsubstate
222 .hgsub .hgsubstate
223
223
224 merge tests
224 merge tests
225
225
226 $ hg co -C 3
226 $ hg co -C 3
227 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
227 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
228 $ hg merge 5 # test adding
228 $ hg merge 5 # test adding
229 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
229 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
230 (branch merge, don't forget to commit)
230 (branch merge, don't forget to commit)
231 $ hg debugsub
231 $ hg debugsub
232 path s
232 path s
233 source s
233 source s
234 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
234 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
235 path t
235 path t
236 source t
236 source t
237 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
237 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
238 $ hg ci -m9
238 $ hg ci -m9
239 created new head
239 created new head
240 $ hg merge 6 --debug # test change
240 $ hg merge 6 --debug # test change
241 searching for copies back to rev 2
241 searching for copies back to rev 2
242 resolving manifests
242 resolving manifests
243 branchmerge: True, force: False, partial: False
243 branchmerge: True, force: False, partial: False
244 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
244 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
245 .hgsubstate: versions differ -> m
245 .hgsubstate: versions differ -> m
246 updating: .hgsubstate 1/1 files (100.00%)
246 updating: .hgsubstate 1/1 files (100.00%)
247 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
247 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
248 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
248 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
249 getting subrepo t
249 getting subrepo t
250 resolving manifests
250 resolving manifests
251 branchmerge: False, force: False, partial: False
251 branchmerge: False, force: False, partial: False
252 ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
252 ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
253 t: remote is newer -> g
253 t: remote is newer -> g
254 getting t
254 getting t
255 updating: t 1/1 files (100.00%)
255 updating: t 1/1 files (100.00%)
256 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
256 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
257 (branch merge, don't forget to commit)
257 (branch merge, don't forget to commit)
258 $ hg debugsub
258 $ hg debugsub
259 path s
259 path s
260 source s
260 source s
261 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
261 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
262 path t
262 path t
263 source t
263 source t
264 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
264 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
265 $ echo conflict > t/t
265 $ echo conflict > t/t
266 $ hg ci -m10
266 $ hg ci -m10
267 committing subrepository t
267 committing subrepository t
268 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
268 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
269 searching for copies back to rev 2
269 searching for copies back to rev 2
270 resolving manifests
270 resolving manifests
271 branchmerge: True, force: False, partial: False
271 branchmerge: True, force: False, partial: False
272 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
272 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
273 .hgsubstate: versions differ -> m
273 .hgsubstate: versions differ -> m
274 updating: .hgsubstate 1/1 files (100.00%)
274 updating: .hgsubstate 1/1 files (100.00%)
275 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
275 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
276 subrepo t: both sides changed
276 subrepo t: both sides changed
277 subrepository t diverged (local revision: 20a0db6fbf6c, remote revision: 7af322bc1198)
277 subrepository t diverged (local revision: 20a0db6fbf6c, remote revision: 7af322bc1198)
278 (M)erge, keep (l)ocal or keep (r)emote? m
278 (M)erge, keep (l)ocal or keep (r)emote? m
279 merging subrepo t
279 merging subrepo t
280 searching for copies back to rev 2
280 searching for copies back to rev 2
281 resolving manifests
281 resolving manifests
282 branchmerge: True, force: False, partial: False
282 branchmerge: True, force: False, partial: False
283 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
283 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
284 preserving t for resolve of t
284 preserving t for resolve of t
285 t: versions differ -> m
285 t: versions differ -> m
286 updating: t 1/1 files (100.00%)
286 updating: t 1/1 files (100.00%)
287 picked tool 'internal:merge' for t (binary False symlink False)
287 picked tool 'internal:merge' for t (binary False symlink False)
288 merging t
288 merging t
289 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
289 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
290 warning: conflicts during merge.
290 warning: conflicts during merge.
291 merging t incomplete! (edit conflicts, then use 'hg resolve --mark')
291 merging t incomplete! (edit conflicts, then use 'hg resolve --mark')
292 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
292 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
293 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
293 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
294 subrepo t: merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
294 subrepo t: merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
295 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
295 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
296 (branch merge, don't forget to commit)
296 (branch merge, don't forget to commit)
297
297
298 should conflict
298 should conflict
299
299
300 $ cat t/t
300 $ cat t/t
301 <<<<<<< local: 20a0db6fbf6c - test: 10
301 <<<<<<< local: 20a0db6fbf6c - test: 10
302 conflict
302 conflict
303 =======
303 =======
304 t3
304 t3
305 >>>>>>> other: 7af322bc1198 - test: 7
305 >>>>>>> other: 7af322bc1198 - test: 7
306
306
307 clone
307 clone
308
308
309 $ cd ..
309 $ cd ..
310 $ hg clone t tc
310 $ hg clone t tc
311 updating to branch default
311 updating to branch default
312 cloning subrepo s from $TESTTMP/t/s
312 cloning subrepo s from $TESTTMP/t/s
313 cloning subrepo s/ss from $TESTTMP/t/s/ss (glob)
313 cloning subrepo s/ss from $TESTTMP/t/s/ss (glob)
314 cloning subrepo t from $TESTTMP/t/t
314 cloning subrepo t from $TESTTMP/t/t
315 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
315 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
316 $ cd tc
316 $ cd tc
317 $ hg debugsub
317 $ hg debugsub
318 path s
318 path s
319 source s
319 source s
320 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
320 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
321 path t
321 path t
322 source t
322 source t
323 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
323 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
324
324
325 push
325 push
326
326
327 $ echo bah > t/t
327 $ echo bah > t/t
328 $ hg ci -m11
328 $ hg ci -m11
329 committing subrepository t
329 committing subrepository t
330 $ hg push
330 $ hg push
331 pushing to $TESTTMP/t (glob)
331 pushing to $TESTTMP/t (glob)
332 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
332 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
333 no changes made to subrepo s since last push to $TESTTMP/t/s
333 no changes made to subrepo s since last push to $TESTTMP/t/s
334 pushing subrepo t to $TESTTMP/t/t
334 pushing subrepo t to $TESTTMP/t/t
335 searching for changes
335 searching for changes
336 adding changesets
336 adding changesets
337 adding manifests
337 adding manifests
338 adding file changes
338 adding file changes
339 added 1 changesets with 1 changes to 1 files
339 added 1 changesets with 1 changes to 1 files
340 searching for changes
340 searching for changes
341 adding changesets
341 adding changesets
342 adding manifests
342 adding manifests
343 adding file changes
343 adding file changes
344 added 1 changesets with 1 changes to 1 files
344 added 1 changesets with 1 changes to 1 files
345
345
346 push -f
346 push -f
347
347
348 $ echo bah > s/a
348 $ echo bah > s/a
349 $ hg ci -m12
349 $ hg ci -m12
350 committing subrepository s
350 committing subrepository s
351 $ hg push
351 $ hg push
352 pushing to $TESTTMP/t (glob)
352 pushing to $TESTTMP/t (glob)
353 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
353 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
354 pushing subrepo s to $TESTTMP/t/s
354 pushing subrepo s to $TESTTMP/t/s
355 searching for changes
355 searching for changes
356 abort: push creates new remote head 12a213df6fa9! (in subrepo s)
356 abort: push creates new remote head 12a213df6fa9! (in subrepo s)
357 (merge or see "hg help push" for details about pushing new heads)
357 (merge or see "hg help push" for details about pushing new heads)
358 [255]
358 [255]
359 $ hg push -f
359 $ hg push -f
360 pushing to $TESTTMP/t (glob)
360 pushing to $TESTTMP/t (glob)
361 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
361 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
362 searching for changes
362 searching for changes
363 no changes found
363 no changes found
364 pushing subrepo s to $TESTTMP/t/s
364 pushing subrepo s to $TESTTMP/t/s
365 searching for changes
365 searching for changes
366 adding changesets
366 adding changesets
367 adding manifests
367 adding manifests
368 adding file changes
368 adding file changes
369 added 1 changesets with 1 changes to 1 files (+1 heads)
369 added 1 changesets with 1 changes to 1 files (+1 heads)
370 pushing subrepo t to $TESTTMP/t/t
370 pushing subrepo t to $TESTTMP/t/t
371 searching for changes
371 searching for changes
372 no changes found
372 no changes found
373 searching for changes
373 searching for changes
374 adding changesets
374 adding changesets
375 adding manifests
375 adding manifests
376 adding file changes
376 adding file changes
377 added 1 changesets with 1 changes to 1 files
377 added 1 changesets with 1 changes to 1 files
378
378
379 check that unmodified subrepos are not pushed
379 check that unmodified subrepos are not pushed
380
380
381 $ hg clone . ../tcc
381 $ hg clone . ../tcc
382 updating to branch default
382 updating to branch default
383 cloning subrepo s from $TESTTMP/tc/s
383 cloning subrepo s from $TESTTMP/tc/s
384 cloning subrepo s/ss from $TESTTMP/tc/s/ss (glob)
384 cloning subrepo s/ss from $TESTTMP/tc/s/ss (glob)
385 cloning subrepo t from $TESTTMP/tc/t
385 cloning subrepo t from $TESTTMP/tc/t
386 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
386 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
387
387
388 the subrepos on the new clone have nothing to push to its source
388 the subrepos on the new clone have nothing to push to its source
389
389
390 $ hg push -R ../tcc .
390 $ hg push -R ../tcc .
391 pushing to .
391 pushing to .
392 no changes made to subrepo s/ss since last push to s/ss (glob)
392 no changes made to subrepo s/ss since last push to s/ss (glob)
393 no changes made to subrepo s since last push to s
393 no changes made to subrepo s since last push to s
394 no changes made to subrepo t since last push to t
394 no changes made to subrepo t since last push to t
395 searching for changes
395 searching for changes
396 no changes found
396 no changes found
397 [1]
397 [1]
398
398
399 the subrepos on the source do not have a clean store versus the clone target
399 the subrepos on the source do not have a clean store versus the clone target
400 because they were never explicitly pushed to the source
400 because they were never explicitly pushed to the source
401
401
402 $ hg push ../tcc
402 $ hg push ../tcc
403 pushing to ../tcc
403 pushing to ../tcc
404 pushing subrepo s/ss to ../tcc/s/ss (glob)
404 pushing subrepo s/ss to ../tcc/s/ss (glob)
405 searching for changes
405 searching for changes
406 no changes found
406 no changes found
407 pushing subrepo s to ../tcc/s
407 pushing subrepo s to ../tcc/s
408 searching for changes
408 searching for changes
409 no changes found
409 no changes found
410 pushing subrepo t to ../tcc/t
410 pushing subrepo t to ../tcc/t
411 searching for changes
411 searching for changes
412 no changes found
412 no changes found
413 searching for changes
413 searching for changes
414 no changes found
414 no changes found
415 [1]
415 [1]
416
416
417 after push their stores become clean
417 after push their stores become clean
418
418
419 $ hg push ../tcc
419 $ hg push ../tcc
420 pushing to ../tcc
420 pushing to ../tcc
421 no changes made to subrepo s/ss since last push to ../tcc/s/ss (glob)
421 no changes made to subrepo s/ss since last push to ../tcc/s/ss (glob)
422 no changes made to subrepo s since last push to ../tcc/s
422 no changes made to subrepo s since last push to ../tcc/s
423 no changes made to subrepo t since last push to ../tcc/t
423 no changes made to subrepo t since last push to ../tcc/t
424 searching for changes
424 searching for changes
425 no changes found
425 no changes found
426 [1]
426 [1]
427
427
428 updating a subrepo to a different revision or changing
428 updating a subrepo to a different revision or changing
429 its working directory does not make its store dirty
429 its working directory does not make its store dirty
430
430
431 $ hg -R s update '.^'
431 $ hg -R s update '.^'
432 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
433 $ hg push
433 $ hg push
434 pushing to $TESTTMP/t (glob)
434 pushing to $TESTTMP/t (glob)
435 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
435 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
436 no changes made to subrepo s since last push to $TESTTMP/t/s
436 no changes made to subrepo s since last push to $TESTTMP/t/s
437 no changes made to subrepo t since last push to $TESTTMP/t/t
437 no changes made to subrepo t since last push to $TESTTMP/t/t
438 searching for changes
438 searching for changes
439 no changes found
439 no changes found
440 [1]
440 [1]
441 $ echo foo >> s/a
441 $ echo foo >> s/a
442 $ hg push
442 $ hg push
443 pushing to $TESTTMP/t (glob)
443 pushing to $TESTTMP/t (glob)
444 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
444 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
445 no changes made to subrepo s since last push to $TESTTMP/t/s
445 no changes made to subrepo s since last push to $TESTTMP/t/s
446 no changes made to subrepo t since last push to $TESTTMP/t/t
446 no changes made to subrepo t since last push to $TESTTMP/t/t
447 searching for changes
447 searching for changes
448 no changes found
448 no changes found
449 [1]
449 [1]
450 $ hg -R s update -C tip
450 $ hg -R s update -C tip
451 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
451 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
452
452
453 committing into a subrepo makes its store (but not its parent's store) dirty
453 committing into a subrepo makes its store (but not its parent's store) dirty
454
454
455 $ echo foo >> s/ss/a
455 $ echo foo >> s/ss/a
456 $ hg -R s/ss commit -m 'test dirty store detection'
456 $ hg -R s/ss commit -m 'test dirty store detection'
457 $ hg push
457 $ hg push
458 pushing to $TESTTMP/t (glob)
458 pushing to $TESTTMP/t (glob)
459 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
459 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
460 searching for changes
460 searching for changes
461 adding changesets
461 adding changesets
462 adding manifests
462 adding manifests
463 adding file changes
463 adding file changes
464 added 1 changesets with 1 changes to 1 files
464 added 1 changesets with 1 changes to 1 files
465 no changes made to subrepo s since last push to $TESTTMP/t/s
465 no changes made to subrepo s since last push to $TESTTMP/t/s
466 no changes made to subrepo t since last push to $TESTTMP/t/t
466 no changes made to subrepo t since last push to $TESTTMP/t/t
467 searching for changes
467 searching for changes
468 no changes found
468 no changes found
469 [1]
469 [1]
470
470
471 a subrepo store may be clean versus one repo but not versus another
471 a subrepo store may be clean versus one repo but not versus another
472
472
473 $ hg push
473 $ hg push
474 pushing to $TESTTMP/t (glob)
474 pushing to $TESTTMP/t (glob)
475 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
475 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
476 no changes made to subrepo s since last push to $TESTTMP/t/s
476 no changes made to subrepo s since last push to $TESTTMP/t/s
477 no changes made to subrepo t since last push to $TESTTMP/t/t
477 no changes made to subrepo t since last push to $TESTTMP/t/t
478 searching for changes
478 searching for changes
479 no changes found
479 no changes found
480 [1]
480 [1]
481 $ hg push ../tcc
481 $ hg push ../tcc
482 pushing to ../tcc
482 pushing to ../tcc
483 pushing subrepo s/ss to ../tcc/s/ss (glob)
483 pushing subrepo s/ss to ../tcc/s/ss (glob)
484 searching for changes
484 searching for changes
485 adding changesets
485 adding changesets
486 adding manifests
486 adding manifests
487 adding file changes
487 adding file changes
488 added 1 changesets with 1 changes to 1 files
488 added 1 changesets with 1 changes to 1 files
489 no changes made to subrepo s since last push to ../tcc/s
489 no changes made to subrepo s since last push to ../tcc/s
490 no changes made to subrepo t since last push to ../tcc/t
490 no changes made to subrepo t since last push to ../tcc/t
491 searching for changes
491 searching for changes
492 no changes found
492 no changes found
493 [1]
493 [1]
494
494
495 update
495 update
496
496
497 $ cd ../t
497 $ cd ../t
498 $ hg up -C # discard our earlier merge
498 $ hg up -C # discard our earlier merge
499 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
499 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
500 $ echo blah > t/t
500 $ echo blah > t/t
501 $ hg ci -m13
501 $ hg ci -m13
502 committing subrepository t
502 committing subrepository t
503
503
504 backout calls revert internally with minimal opts, which should not raise
504 backout calls revert internally with minimal opts, which should not raise
505 KeyError
505 KeyError
506
506
507 $ hg backout ".^"
507 $ hg backout ".^"
508 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
508 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
509 changeset c373c8102e68 backed out, don't forget to commit.
509 changeset c373c8102e68 backed out, don't forget to commit.
510
510
511 $ hg up -C # discard changes
511 $ hg up -C # discard changes
512 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
512 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
513
513
514 pull
514 pull
515
515
516 $ cd ../tc
516 $ cd ../tc
517 $ hg pull
517 $ hg pull
518 pulling from $TESTTMP/t (glob)
518 pulling from $TESTTMP/t (glob)
519 searching for changes
519 searching for changes
520 adding changesets
520 adding changesets
521 adding manifests
521 adding manifests
522 adding file changes
522 adding file changes
523 added 1 changesets with 1 changes to 1 files
523 added 1 changesets with 1 changes to 1 files
524 (run 'hg update' to get a working copy)
524 (run 'hg update' to get a working copy)
525
525
526 should pull t
526 should pull t
527
527
528 $ hg up
528 $ hg up
529 pulling subrepo t from $TESTTMP/t/t
529 pulling subrepo t from $TESTTMP/t/t
530 searching for changes
530 searching for changes
531 adding changesets
531 adding changesets
532 adding manifests
532 adding manifests
533 adding file changes
533 adding file changes
534 added 1 changesets with 1 changes to 1 files
534 added 1 changesets with 1 changes to 1 files
535 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
535 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
536 $ cat t/t
536 $ cat t/t
537 blah
537 blah
538
538
539 bogus subrepo path aborts
539 bogus subrepo path aborts
540
540
541 $ echo 'bogus=[boguspath' >> .hgsub
541 $ echo 'bogus=[boguspath' >> .hgsub
542 $ hg ci -m 'bogus subrepo path'
542 $ hg ci -m 'bogus subrepo path'
543 abort: missing ] in subrepo source
543 abort: missing ] in subrepo source
544 [255]
544 [255]
545
545
546 Issue1986: merge aborts when trying to merge a subrepo that
546 Issue1986: merge aborts when trying to merge a subrepo that
547 shouldn't need merging
547 shouldn't need merging
548
548
549 # subrepo layout
549 # subrepo layout
550 #
550 #
551 # o 5 br
551 # o 5 br
552 # /|
552 # /|
553 # o | 4 default
553 # o | 4 default
554 # | |
554 # | |
555 # | o 3 br
555 # | o 3 br
556 # |/|
556 # |/|
557 # o | 2 default
557 # o | 2 default
558 # | |
558 # | |
559 # | o 1 br
559 # | o 1 br
560 # |/
560 # |/
561 # o 0 default
561 # o 0 default
562
562
563 $ cd ..
563 $ cd ..
564 $ rm -rf sub
564 $ rm -rf sub
565 $ hg init main
565 $ hg init main
566 $ cd main
566 $ cd main
567 $ hg init s
567 $ hg init s
568 $ cd s
568 $ cd s
569 $ echo a > a
569 $ echo a > a
570 $ hg ci -Am1
570 $ hg ci -Am1
571 adding a
571 adding a
572 $ hg branch br
572 $ hg branch br
573 marked working directory as branch br
573 marked working directory as branch br
574 (branches are permanent and global, did you want a bookmark?)
574 (branches are permanent and global, did you want a bookmark?)
575 $ echo a >> a
575 $ echo a >> a
576 $ hg ci -m1
576 $ hg ci -m1
577 $ hg up default
577 $ hg up default
578 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
578 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
579 $ echo b > b
579 $ echo b > b
580 $ hg ci -Am1
580 $ hg ci -Am1
581 adding b
581 adding b
582 $ hg up br
582 $ hg up br
583 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
583 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
584 $ hg merge tip
584 $ hg merge tip
585 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
585 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
586 (branch merge, don't forget to commit)
586 (branch merge, don't forget to commit)
587 $ hg ci -m1
587 $ hg ci -m1
588 $ hg up 2
588 $ hg up 2
589 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
589 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
590 $ echo c > c
590 $ echo c > c
591 $ hg ci -Am1
591 $ hg ci -Am1
592 adding c
592 adding c
593 $ hg up 3
593 $ hg up 3
594 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
594 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
595 $ hg merge 4
595 $ hg merge 4
596 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
596 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
597 (branch merge, don't forget to commit)
597 (branch merge, don't forget to commit)
598 $ hg ci -m1
598 $ hg ci -m1
599
599
600 # main repo layout:
600 # main repo layout:
601 #
601 #
602 # * <-- try to merge default into br again
602 # * <-- try to merge default into br again
603 # .`|
603 # .`|
604 # . o 5 br --> substate = 5
604 # . o 5 br --> substate = 5
605 # . |
605 # . |
606 # o | 4 default --> substate = 4
606 # o | 4 default --> substate = 4
607 # | |
607 # | |
608 # | o 3 br --> substate = 2
608 # | o 3 br --> substate = 2
609 # |/|
609 # |/|
610 # o | 2 default --> substate = 2
610 # o | 2 default --> substate = 2
611 # | |
611 # | |
612 # | o 1 br --> substate = 3
612 # | o 1 br --> substate = 3
613 # |/
613 # |/
614 # o 0 default --> substate = 2
614 # o 0 default --> substate = 2
615
615
616 $ cd ..
616 $ cd ..
617 $ echo 's = s' > .hgsub
617 $ echo 's = s' > .hgsub
618 $ hg -R s up 2
618 $ hg -R s up 2
619 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
619 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
620 $ hg ci -Am1
620 $ hg ci -Am1
621 adding .hgsub
621 adding .hgsub
622 $ hg branch br
622 $ hg branch br
623 marked working directory as branch br
623 marked working directory as branch br
624 (branches are permanent and global, did you want a bookmark?)
624 (branches are permanent and global, did you want a bookmark?)
625 $ echo b > b
625 $ echo b > b
626 $ hg -R s up 3
626 $ hg -R s up 3
627 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
627 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
628 $ hg ci -Am1
628 $ hg ci -Am1
629 adding b
629 adding b
630 $ hg up default
630 $ hg up default
631 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
631 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
632 $ echo c > c
632 $ echo c > c
633 $ hg ci -Am1
633 $ hg ci -Am1
634 adding c
634 adding c
635 $ hg up 1
635 $ hg up 1
636 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
636 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
637 $ hg merge 2
637 $ hg merge 2
638 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
638 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
639 (branch merge, don't forget to commit)
639 (branch merge, don't forget to commit)
640 $ hg ci -m1
640 $ hg ci -m1
641 $ hg up 2
641 $ hg up 2
642 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
642 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
643 $ hg -R s up 4
643 $ hg -R s up 4
644 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
644 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
645 $ echo d > d
645 $ echo d > d
646 $ hg ci -Am1
646 $ hg ci -Am1
647 adding d
647 adding d
648 $ hg up 3
648 $ hg up 3
649 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
649 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
650 $ hg -R s up 5
650 $ hg -R s up 5
651 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
651 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
652 $ echo e > e
652 $ echo e > e
653 $ hg ci -Am1
653 $ hg ci -Am1
654 adding e
654 adding e
655
655
656 $ hg up 5
656 $ hg up 5
657 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
657 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
658 $ hg merge 4 # try to merge default into br again
658 $ hg merge 4 # try to merge default into br again
659 subrepository s diverged (local revision: f8f13b33206e, remote revision: a3f9062a4f88)
659 subrepository s diverged (local revision: f8f13b33206e, remote revision: a3f9062a4f88)
660 (M)erge, keep (l)ocal or keep (r)emote? m
660 (M)erge, keep (l)ocal or keep (r)emote? m
661 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
661 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
662 (branch merge, don't forget to commit)
662 (branch merge, don't forget to commit)
663 $ cd ..
663 $ cd ..
664
664
665 test subrepo delete from .hgsubstate
665 test subrepo delete from .hgsubstate
666
666
667 $ hg init testdelete
667 $ hg init testdelete
668 $ mkdir testdelete/nested testdelete/nested2
668 $ mkdir testdelete/nested testdelete/nested2
669 $ hg init testdelete/nested
669 $ hg init testdelete/nested
670 $ hg init testdelete/nested2
670 $ hg init testdelete/nested2
671 $ echo test > testdelete/nested/foo
671 $ echo test > testdelete/nested/foo
672 $ echo test > testdelete/nested2/foo
672 $ echo test > testdelete/nested2/foo
673 $ hg -R testdelete/nested add
673 $ hg -R testdelete/nested add
674 adding testdelete/nested/foo (glob)
674 adding testdelete/nested/foo (glob)
675 $ hg -R testdelete/nested2 add
675 $ hg -R testdelete/nested2 add
676 adding testdelete/nested2/foo (glob)
676 adding testdelete/nested2/foo (glob)
677 $ hg -R testdelete/nested ci -m test
677 $ hg -R testdelete/nested ci -m test
678 $ hg -R testdelete/nested2 ci -m test
678 $ hg -R testdelete/nested2 ci -m test
679 $ echo nested = nested > testdelete/.hgsub
679 $ echo nested = nested > testdelete/.hgsub
680 $ echo nested2 = nested2 >> testdelete/.hgsub
680 $ echo nested2 = nested2 >> testdelete/.hgsub
681 $ hg -R testdelete add
681 $ hg -R testdelete add
682 adding testdelete/.hgsub (glob)
682 adding testdelete/.hgsub (glob)
683 $ hg -R testdelete ci -m "nested 1 & 2 added"
683 $ hg -R testdelete ci -m "nested 1 & 2 added"
684 $ echo nested = nested > testdelete/.hgsub
684 $ echo nested = nested > testdelete/.hgsub
685 $ hg -R testdelete ci -m "nested 2 deleted"
685 $ hg -R testdelete ci -m "nested 2 deleted"
686 $ cat testdelete/.hgsubstate
686 $ cat testdelete/.hgsubstate
687 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
687 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
688 $ hg -R testdelete remove testdelete/.hgsub
688 $ hg -R testdelete remove testdelete/.hgsub
689 $ hg -R testdelete ci -m ".hgsub deleted"
689 $ hg -R testdelete ci -m ".hgsub deleted"
690 $ cat testdelete/.hgsubstate
690 $ cat testdelete/.hgsubstate
691 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
691 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
692
692
693 test repository cloning
693 test repository cloning
694
694
695 $ mkdir mercurial mercurial2
695 $ mkdir mercurial mercurial2
696 $ hg init nested_absolute
696 $ hg init nested_absolute
697 $ echo test > nested_absolute/foo
697 $ echo test > nested_absolute/foo
698 $ hg -R nested_absolute add
698 $ hg -R nested_absolute add
699 adding nested_absolute/foo (glob)
699 adding nested_absolute/foo (glob)
700 $ hg -R nested_absolute ci -mtest
700 $ hg -R nested_absolute ci -mtest
701 $ cd mercurial
701 $ cd mercurial
702 $ hg init nested_relative
702 $ hg init nested_relative
703 $ echo test2 > nested_relative/foo2
703 $ echo test2 > nested_relative/foo2
704 $ hg -R nested_relative add
704 $ hg -R nested_relative add
705 adding nested_relative/foo2 (glob)
705 adding nested_relative/foo2 (glob)
706 $ hg -R nested_relative ci -mtest2
706 $ hg -R nested_relative ci -mtest2
707 $ hg init main
707 $ hg init main
708 $ echo "nested_relative = ../nested_relative" > main/.hgsub
708 $ echo "nested_relative = ../nested_relative" > main/.hgsub
709 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
709 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
710 $ hg -R main add
710 $ hg -R main add
711 adding main/.hgsub (glob)
711 adding main/.hgsub (glob)
712 $ hg -R main ci -m "add subrepos"
712 $ hg -R main ci -m "add subrepos"
713 $ cd ..
713 $ cd ..
714 $ hg clone mercurial/main mercurial2/main
714 $ hg clone mercurial/main mercurial2/main
715 updating to branch default
715 updating to branch default
716 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
716 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
717 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
717 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
718 > mercurial2/main/nested_relative/.hg/hgrc
718 > mercurial2/main/nested_relative/.hg/hgrc
719 [paths]
719 [paths]
720 default = $TESTTMP/mercurial/nested_absolute
720 default = $TESTTMP/mercurial/nested_absolute
721 [paths]
721 [paths]
722 default = $TESTTMP/mercurial/nested_relative
722 default = $TESTTMP/mercurial/nested_relative
723 $ rm -rf mercurial mercurial2
723 $ rm -rf mercurial mercurial2
724
724
725 Issue1977: multirepo push should fail if subrepo push fails
725 Issue1977: multirepo push should fail if subrepo push fails
726
726
727 $ hg init repo
727 $ hg init repo
728 $ hg init repo/s
728 $ hg init repo/s
729 $ echo a > repo/s/a
729 $ echo a > repo/s/a
730 $ hg -R repo/s ci -Am0
730 $ hg -R repo/s ci -Am0
731 adding a
731 adding a
732 $ echo s = s > repo/.hgsub
732 $ echo s = s > repo/.hgsub
733 $ hg -R repo ci -Am1
733 $ hg -R repo ci -Am1
734 adding .hgsub
734 adding .hgsub
735 $ hg clone repo repo2
735 $ hg clone repo repo2
736 updating to branch default
736 updating to branch default
737 cloning subrepo s from $TESTTMP/repo/s
737 cloning subrepo s from $TESTTMP/repo/s
738 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
738 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
739 $ hg -q -R repo2 pull -u
739 $ hg -q -R repo2 pull -u
740 $ echo 1 > repo2/s/a
740 $ echo 1 > repo2/s/a
741 $ hg -R repo2/s ci -m2
741 $ hg -R repo2/s ci -m2
742 $ hg -q -R repo2/s push
742 $ hg -q -R repo2/s push
743 $ hg -R repo2/s up -C 0
743 $ hg -R repo2/s up -C 0
744 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
744 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
745 $ echo 2 > repo2/s/b
745 $ echo 2 > repo2/s/b
746 $ hg -R repo2/s ci -m3 -A
746 $ hg -R repo2/s ci -m3 -A
747 adding b
747 adding b
748 created new head
748 created new head
749 $ hg -R repo2 ci -m3
749 $ hg -R repo2 ci -m3
750 $ hg -q -R repo2 push
750 $ hg -q -R repo2 push
751 abort: push creates new remote head cc505f09a8b2! (in subrepo s)
751 abort: push creates new remote head cc505f09a8b2! (in subrepo s)
752 (merge or see "hg help push" for details about pushing new heads)
752 (merge or see "hg help push" for details about pushing new heads)
753 [255]
753 [255]
754 $ hg -R repo update
754 $ hg -R repo update
755 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
755 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
756
756
757 test if untracked file is not overwritten
757 test if untracked file is not overwritten
758
758
759 $ echo issue3276_ok > repo/s/b
759 $ echo issue3276_ok > repo/s/b
760 $ hg -R repo2 push -f -q
760 $ hg -R repo2 push -f -q
761 $ touch -t 200001010000 repo/.hgsubstate
762 $ hg -R repo status --config debug.dirstate.delaywrite=2 repo/.hgsubstate
761 $ hg -R repo update
763 $ hg -R repo update
762 b: untracked file differs
764 b: untracked file differs
763 abort: untracked files in working directory differ from files in requested revision (in subrepo s)
765 abort: untracked files in working directory differ from files in requested revision (in subrepo s)
764 [255]
766 [255]
765
767
766 $ cat repo/s/b
768 $ cat repo/s/b
767 issue3276_ok
769 issue3276_ok
768 $ rm repo/s/b
770 $ rm repo/s/b
771 $ touch -t 200001010000 repo/.hgsubstate
769 $ hg -R repo revert --all
772 $ hg -R repo revert --all
770 reverting repo/.hgsubstate (glob)
773 reverting repo/.hgsubstate (glob)
771 reverting subrepo s
774 reverting subrepo s
772 $ hg -R repo update
775 $ hg -R repo update
773 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
776 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
774 $ cat repo/s/b
777 $ cat repo/s/b
775 2
778 2
776 $ rm -rf repo2 repo
779 $ rm -rf repo2 repo
777
780
778
781
779 Issue1852 subrepos with relative paths always push/pull relative to default
782 Issue1852 subrepos with relative paths always push/pull relative to default
780
783
781 Prepare a repo with subrepo
784 Prepare a repo with subrepo
782
785
783 $ hg init issue1852a
786 $ hg init issue1852a
784 $ cd issue1852a
787 $ cd issue1852a
785 $ hg init sub/repo
788 $ hg init sub/repo
786 $ echo test > sub/repo/foo
789 $ echo test > sub/repo/foo
787 $ hg -R sub/repo add sub/repo/foo
790 $ hg -R sub/repo add sub/repo/foo
788 $ echo sub/repo = sub/repo > .hgsub
791 $ echo sub/repo = sub/repo > .hgsub
789 $ hg add .hgsub
792 $ hg add .hgsub
790 $ hg ci -mtest
793 $ hg ci -mtest
791 committing subrepository sub/repo (glob)
794 committing subrepository sub/repo (glob)
792 $ echo test >> sub/repo/foo
795 $ echo test >> sub/repo/foo
793 $ hg ci -mtest
796 $ hg ci -mtest
794 committing subrepository sub/repo (glob)
797 committing subrepository sub/repo (glob)
795 $ hg cat sub/repo/foo
798 $ hg cat sub/repo/foo
796 test
799 test
797 test
800 test
798 $ mkdir -p tmp/sub/repo
801 $ mkdir -p tmp/sub/repo
799 $ hg cat -r 0 --output tmp/%p_p sub/repo/foo
802 $ hg cat -r 0 --output tmp/%p_p sub/repo/foo
800 $ cat tmp/sub/repo/foo_p
803 $ cat tmp/sub/repo/foo_p
801 test
804 test
802 $ mv sub/repo sub_
805 $ mv sub/repo sub_
803 $ hg cat sub/repo/baz
806 $ hg cat sub/repo/baz
804 skipping missing subrepository: sub/repo
807 skipping missing subrepository: sub/repo
805 [1]
808 [1]
806 $ rm -rf sub/repo
809 $ rm -rf sub/repo
807 $ mv sub_ sub/repo
810 $ mv sub_ sub/repo
808 $ cd ..
811 $ cd ..
809
812
810 Create repo without default path, pull top repo, and see what happens on update
813 Create repo without default path, pull top repo, and see what happens on update
811
814
812 $ hg init issue1852b
815 $ hg init issue1852b
813 $ hg -R issue1852b pull issue1852a
816 $ hg -R issue1852b pull issue1852a
814 pulling from issue1852a
817 pulling from issue1852a
815 requesting all changes
818 requesting all changes
816 adding changesets
819 adding changesets
817 adding manifests
820 adding manifests
818 adding file changes
821 adding file changes
819 added 2 changesets with 3 changes to 2 files
822 added 2 changesets with 3 changes to 2 files
820 (run 'hg update' to get a working copy)
823 (run 'hg update' to get a working copy)
821 $ hg -R issue1852b update
824 $ hg -R issue1852b update
822 abort: default path for subrepository not found (in subrepo sub/repo) (glob)
825 abort: default path for subrepository not found (in subrepo sub/repo) (glob)
823 [255]
826 [255]
824
827
825 Ensure a full traceback, not just the SubrepoAbort part
828 Ensure a full traceback, not just the SubrepoAbort part
826
829
827 $ hg -R issue1852b update --traceback 2>&1 | grep 'raise util\.Abort'
830 $ hg -R issue1852b update --traceback 2>&1 | grep 'raise util\.Abort'
828 raise util.Abort(_("default path for subrepository not found"))
831 raise util.Abort(_("default path for subrepository not found"))
829
832
830 Pull -u now doesn't help
833 Pull -u now doesn't help
831
834
832 $ hg -R issue1852b pull -u issue1852a
835 $ hg -R issue1852b pull -u issue1852a
833 pulling from issue1852a
836 pulling from issue1852a
834 searching for changes
837 searching for changes
835 no changes found
838 no changes found
836
839
837 Try the same, but with pull -u
840 Try the same, but with pull -u
838
841
839 $ hg init issue1852c
842 $ hg init issue1852c
840 $ hg -R issue1852c pull -r0 -u issue1852a
843 $ hg -R issue1852c pull -r0 -u issue1852a
841 pulling from issue1852a
844 pulling from issue1852a
842 adding changesets
845 adding changesets
843 adding manifests
846 adding manifests
844 adding file changes
847 adding file changes
845 added 1 changesets with 2 changes to 2 files
848 added 1 changesets with 2 changes to 2 files
846 cloning subrepo sub/repo from issue1852a/sub/repo (glob)
849 cloning subrepo sub/repo from issue1852a/sub/repo (glob)
847 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
850 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
848
851
849 Try to push from the other side
852 Try to push from the other side
850
853
851 $ hg -R issue1852a push `pwd`/issue1852c
854 $ hg -R issue1852a push `pwd`/issue1852c
852 pushing to $TESTTMP/issue1852c (glob)
855 pushing to $TESTTMP/issue1852c (glob)
853 pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo (glob)
856 pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo (glob)
854 searching for changes
857 searching for changes
855 no changes found
858 no changes found
856 searching for changes
859 searching for changes
857 adding changesets
860 adding changesets
858 adding manifests
861 adding manifests
859 adding file changes
862 adding file changes
860 added 1 changesets with 1 changes to 1 files
863 added 1 changesets with 1 changes to 1 files
861
864
862 Incoming and outgoing should not use the default path:
865 Incoming and outgoing should not use the default path:
863
866
864 $ hg clone -q issue1852a issue1852d
867 $ hg clone -q issue1852a issue1852d
865 $ hg -R issue1852d outgoing --subrepos issue1852c
868 $ hg -R issue1852d outgoing --subrepos issue1852c
866 comparing with issue1852c
869 comparing with issue1852c
867 searching for changes
870 searching for changes
868 no changes found
871 no changes found
869 comparing with issue1852c/sub/repo
872 comparing with issue1852c/sub/repo
870 searching for changes
873 searching for changes
871 no changes found
874 no changes found
872 [1]
875 [1]
873 $ hg -R issue1852d incoming --subrepos issue1852c
876 $ hg -R issue1852d incoming --subrepos issue1852c
874 comparing with issue1852c
877 comparing with issue1852c
875 searching for changes
878 searching for changes
876 no changes found
879 no changes found
877 comparing with issue1852c/sub/repo
880 comparing with issue1852c/sub/repo
878 searching for changes
881 searching for changes
879 no changes found
882 no changes found
880 [1]
883 [1]
881
884
882 Check status of files when none of them belong to the first
885 Check status of files when none of them belong to the first
883 subrepository:
886 subrepository:
884
887
885 $ hg init subrepo-status
888 $ hg init subrepo-status
886 $ cd subrepo-status
889 $ cd subrepo-status
887 $ hg init subrepo-1
890 $ hg init subrepo-1
888 $ hg init subrepo-2
891 $ hg init subrepo-2
889 $ cd subrepo-2
892 $ cd subrepo-2
890 $ touch file
893 $ touch file
891 $ hg add file
894 $ hg add file
892 $ cd ..
895 $ cd ..
893 $ echo subrepo-1 = subrepo-1 > .hgsub
896 $ echo subrepo-1 = subrepo-1 > .hgsub
894 $ echo subrepo-2 = subrepo-2 >> .hgsub
897 $ echo subrepo-2 = subrepo-2 >> .hgsub
895 $ hg add .hgsub
898 $ hg add .hgsub
896 $ hg ci -m 'Added subrepos'
899 $ hg ci -m 'Added subrepos'
897 committing subrepository subrepo-2
900 committing subrepository subrepo-2
898 $ hg st subrepo-2/file
901 $ hg st subrepo-2/file
899
902
900 Check that share works with subrepo
903 Check that share works with subrepo
901 $ hg --config extensions.share= share . ../shared
904 $ hg --config extensions.share= share . ../shared
902 updating working directory
905 updating working directory
903 cloning subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
906 cloning subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
904 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
907 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
905 $ test -f ../shared/subrepo-1/.hg/sharedpath
908 $ test -f ../shared/subrepo-1/.hg/sharedpath
906 [1]
909 [1]
907 $ hg -R ../shared in
910 $ hg -R ../shared in
908 abort: repository default not found!
911 abort: repository default not found!
909 [255]
912 [255]
910 $ hg -R ../shared/subrepo-2 showconfig paths
913 $ hg -R ../shared/subrepo-2 showconfig paths
911 paths.default=$TESTTMP/subrepo-status/subrepo-2
914 paths.default=$TESTTMP/subrepo-status/subrepo-2
912 $ hg -R ../shared/subrepo-1 sum --remote
915 $ hg -R ../shared/subrepo-1 sum --remote
913 parent: -1:000000000000 tip (empty repository)
916 parent: -1:000000000000 tip (empty repository)
914 branch: default
917 branch: default
915 commit: (clean)
918 commit: (clean)
916 update: (current)
919 update: (current)
917 remote: (synced)
920 remote: (synced)
918
921
919 Check hg update --clean
922 Check hg update --clean
920 $ cd $TESTTMP/t
923 $ cd $TESTTMP/t
921 $ rm -r t/t.orig
924 $ rm -r t/t.orig
922 $ hg status -S --all
925 $ hg status -S --all
923 C .hgsub
926 C .hgsub
924 C .hgsubstate
927 C .hgsubstate
925 C a
928 C a
926 C s/.hgsub
929 C s/.hgsub
927 C s/.hgsubstate
930 C s/.hgsubstate
928 C s/a
931 C s/a
929 C s/ss/a
932 C s/ss/a
930 C t/t
933 C t/t
931 $ echo c1 > s/a
934 $ echo c1 > s/a
932 $ cd s
935 $ cd s
933 $ echo c1 > b
936 $ echo c1 > b
934 $ echo c1 > c
937 $ echo c1 > c
935 $ hg add b
938 $ hg add b
936 $ cd ..
939 $ cd ..
937 $ hg status -S
940 $ hg status -S
938 M s/a
941 M s/a
939 A s/b
942 A s/b
940 ? s/c
943 ? s/c
941 $ hg update -C
944 $ hg update -C
942 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
945 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
943 $ hg status -S
946 $ hg status -S
944 ? s/b
947 ? s/b
945 ? s/c
948 ? s/c
946
949
947 Sticky subrepositories, no changes
950 Sticky subrepositories, no changes
948 $ cd $TESTTMP/t
951 $ cd $TESTTMP/t
949 $ hg id
952 $ hg id
950 925c17564ef8 tip
953 925c17564ef8 tip
951 $ hg -R s id
954 $ hg -R s id
952 12a213df6fa9 tip
955 12a213df6fa9 tip
953 $ hg -R t id
956 $ hg -R t id
954 52c0adc0515a tip
957 52c0adc0515a tip
955 $ hg update 11
958 $ hg update 11
956 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
959 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
957 $ hg id
960 $ hg id
958 365661e5936a
961 365661e5936a
959 $ hg -R s id
962 $ hg -R s id
960 fc627a69481f
963 fc627a69481f
961 $ hg -R t id
964 $ hg -R t id
962 e95bcfa18a35
965 e95bcfa18a35
963
966
964 Sticky subrepositories, file changes
967 Sticky subrepositories, file changes
965 $ touch s/f1
968 $ touch s/f1
966 $ touch t/f1
969 $ touch t/f1
967 $ hg add -S s/f1
970 $ hg add -S s/f1
968 $ hg add -S t/f1
971 $ hg add -S t/f1
969 $ hg id
972 $ hg id
970 365661e5936a+
973 365661e5936a+
971 $ hg -R s id
974 $ hg -R s id
972 fc627a69481f+
975 fc627a69481f+
973 $ hg -R t id
976 $ hg -R t id
974 e95bcfa18a35+
977 e95bcfa18a35+
975 $ hg update tip
978 $ hg update tip
976 subrepository s diverged (local revision: fc627a69481f, remote revision: 12a213df6fa9)
979 subrepository s diverged (local revision: fc627a69481f, remote revision: 12a213df6fa9)
977 (M)erge, keep (l)ocal or keep (r)emote? m
980 (M)erge, keep (l)ocal or keep (r)emote? m
978 subrepository sources for s differ
981 subrepository sources for s differ
979 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)? l
982 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)? l
980 subrepository t diverged (local revision: e95bcfa18a35, remote revision: 52c0adc0515a)
983 subrepository t diverged (local revision: e95bcfa18a35, remote revision: 52c0adc0515a)
981 (M)erge, keep (l)ocal or keep (r)emote? m
984 (M)erge, keep (l)ocal or keep (r)emote? m
982 subrepository sources for t differ
985 subrepository sources for t differ
983 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)? l
986 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)? l
984 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
987 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
985 $ hg id
988 $ hg id
986 925c17564ef8+ tip
989 925c17564ef8+ tip
987 $ hg -R s id
990 $ hg -R s id
988 fc627a69481f+
991 fc627a69481f+
989 $ hg -R t id
992 $ hg -R t id
990 e95bcfa18a35+
993 e95bcfa18a35+
991 $ hg update --clean tip
994 $ hg update --clean tip
992 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
995 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
993
996
994 Sticky subrepository, revision updates
997 Sticky subrepository, revision updates
995 $ hg id
998 $ hg id
996 925c17564ef8 tip
999 925c17564ef8 tip
997 $ hg -R s id
1000 $ hg -R s id
998 12a213df6fa9 tip
1001 12a213df6fa9 tip
999 $ hg -R t id
1002 $ hg -R t id
1000 52c0adc0515a tip
1003 52c0adc0515a tip
1001 $ cd s
1004 $ cd s
1002 $ hg update -r -2
1005 $ hg update -r -2
1003 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1006 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1004 $ cd ../t
1007 $ cd ../t
1005 $ hg update -r 2
1008 $ hg update -r 2
1006 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1009 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1007 $ cd ..
1010 $ cd ..
1008 $ hg update 10
1011 $ hg update 10
1009 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1012 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1010 (M)erge, keep (l)ocal or keep (r)emote? m
1013 (M)erge, keep (l)ocal or keep (r)emote? m
1011 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 20a0db6fbf6c)
1014 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 20a0db6fbf6c)
1012 (M)erge, keep (l)ocal or keep (r)emote? m
1015 (M)erge, keep (l)ocal or keep (r)emote? m
1013 subrepository sources for t differ (in checked out version)
1016 subrepository sources for t differ (in checked out version)
1014 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)? l
1017 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)? l
1015 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1018 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1016 $ hg id
1019 $ hg id
1017 e45c8b14af55+
1020 e45c8b14af55+
1018 $ hg -R s id
1021 $ hg -R s id
1019 02dcf1d70411
1022 02dcf1d70411
1020 $ hg -R t id
1023 $ hg -R t id
1021 7af322bc1198
1024 7af322bc1198
1022
1025
1023 Sticky subrepository, file changes and revision updates
1026 Sticky subrepository, file changes and revision updates
1024 $ touch s/f1
1027 $ touch s/f1
1025 $ touch t/f1
1028 $ touch t/f1
1026 $ hg add -S s/f1
1029 $ hg add -S s/f1
1027 $ hg add -S t/f1
1030 $ hg add -S t/f1
1028 $ hg id
1031 $ hg id
1029 e45c8b14af55+
1032 e45c8b14af55+
1030 $ hg -R s id
1033 $ hg -R s id
1031 02dcf1d70411+
1034 02dcf1d70411+
1032 $ hg -R t id
1035 $ hg -R t id
1033 7af322bc1198+
1036 7af322bc1198+
1034 $ hg update tip
1037 $ hg update tip
1035 subrepository s diverged (local revision: 12a213df6fa9, remote revision: 12a213df6fa9)
1038 subrepository s diverged (local revision: 12a213df6fa9, remote revision: 12a213df6fa9)
1036 (M)erge, keep (l)ocal or keep (r)emote? m
1039 (M)erge, keep (l)ocal or keep (r)emote? m
1037 subrepository sources for s differ
1040 subrepository sources for s differ
1038 use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)? l
1041 use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)? l
1039 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 52c0adc0515a)
1042 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 52c0adc0515a)
1040 (M)erge, keep (l)ocal or keep (r)emote? m
1043 (M)erge, keep (l)ocal or keep (r)emote? m
1041 subrepository sources for t differ
1044 subrepository sources for t differ
1042 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)? l
1045 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)? l
1043 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1046 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1044 $ hg id
1047 $ hg id
1045 925c17564ef8+ tip
1048 925c17564ef8+ tip
1046 $ hg -R s id
1049 $ hg -R s id
1047 02dcf1d70411+
1050 02dcf1d70411+
1048 $ hg -R t id
1051 $ hg -R t id
1049 7af322bc1198+
1052 7af322bc1198+
1050
1053
1051 Sticky repository, update --clean
1054 Sticky repository, update --clean
1052 $ hg update --clean tip
1055 $ hg update --clean tip
1053 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1056 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1054 $ hg id
1057 $ hg id
1055 925c17564ef8 tip
1058 925c17564ef8 tip
1056 $ hg -R s id
1059 $ hg -R s id
1057 12a213df6fa9 tip
1060 12a213df6fa9 tip
1058 $ hg -R t id
1061 $ hg -R t id
1059 52c0adc0515a tip
1062 52c0adc0515a tip
1060
1063
1061 Test subrepo already at intended revision:
1064 Test subrepo already at intended revision:
1062 $ cd s
1065 $ cd s
1063 $ hg update fc627a69481f
1066 $ hg update fc627a69481f
1064 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1067 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1065 $ cd ..
1068 $ cd ..
1066 $ hg update 11
1069 $ hg update 11
1067 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1070 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1068 (M)erge, keep (l)ocal or keep (r)emote? m
1071 (M)erge, keep (l)ocal or keep (r)emote? m
1069 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1072 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1070 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1073 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1071 $ hg id -n
1074 $ hg id -n
1072 11+
1075 11+
1073 $ hg -R s id
1076 $ hg -R s id
1074 fc627a69481f
1077 fc627a69481f
1075 $ hg -R t id
1078 $ hg -R t id
1076 e95bcfa18a35
1079 e95bcfa18a35
1077
1080
1078 Test that removing .hgsubstate doesn't break anything:
1081 Test that removing .hgsubstate doesn't break anything:
1079
1082
1080 $ hg rm -f .hgsubstate
1083 $ hg rm -f .hgsubstate
1081 $ hg ci -mrm
1084 $ hg ci -mrm
1082 nothing changed
1085 nothing changed
1083 [1]
1086 [1]
1084 $ hg log -vr tip
1087 $ hg log -vr tip
1085 changeset: 13:925c17564ef8
1088 changeset: 13:925c17564ef8
1086 tag: tip
1089 tag: tip
1087 user: test
1090 user: test
1088 date: Thu Jan 01 00:00:00 1970 +0000
1091 date: Thu Jan 01 00:00:00 1970 +0000
1089 files: .hgsubstate
1092 files: .hgsubstate
1090 description:
1093 description:
1091 13
1094 13
1092
1095
1093
1096
1094
1097
1095 Test that removing .hgsub removes .hgsubstate:
1098 Test that removing .hgsub removes .hgsubstate:
1096
1099
1097 $ hg rm .hgsub
1100 $ hg rm .hgsub
1098 $ hg ci -mrm2
1101 $ hg ci -mrm2
1099 created new head
1102 created new head
1100 $ hg log -vr tip
1103 $ hg log -vr tip
1101 changeset: 14:2400bccd50af
1104 changeset: 14:2400bccd50af
1102 tag: tip
1105 tag: tip
1103 parent: 11:365661e5936a
1106 parent: 11:365661e5936a
1104 user: test
1107 user: test
1105 date: Thu Jan 01 00:00:00 1970 +0000
1108 date: Thu Jan 01 00:00:00 1970 +0000
1106 files: .hgsub .hgsubstate
1109 files: .hgsub .hgsubstate
1107 description:
1110 description:
1108 rm2
1111 rm2
1109
1112
1110
1113
1111 Test issue3153: diff -S with deleted subrepos
1114 Test issue3153: diff -S with deleted subrepos
1112
1115
1113 $ hg diff --nodates -S -c .
1116 $ hg diff --nodates -S -c .
1114 diff -r 365661e5936a -r 2400bccd50af .hgsub
1117 diff -r 365661e5936a -r 2400bccd50af .hgsub
1115 --- a/.hgsub
1118 --- a/.hgsub
1116 +++ /dev/null
1119 +++ /dev/null
1117 @@ -1,2 +0,0 @@
1120 @@ -1,2 +0,0 @@
1118 -s = s
1121 -s = s
1119 -t = t
1122 -t = t
1120 diff -r 365661e5936a -r 2400bccd50af .hgsubstate
1123 diff -r 365661e5936a -r 2400bccd50af .hgsubstate
1121 --- a/.hgsubstate
1124 --- a/.hgsubstate
1122 +++ /dev/null
1125 +++ /dev/null
1123 @@ -1,2 +0,0 @@
1126 @@ -1,2 +0,0 @@
1124 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1127 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1125 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
1128 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
1126
1129
1127 Test behavior of add for explicit path in subrepo:
1130 Test behavior of add for explicit path in subrepo:
1128 $ cd ..
1131 $ cd ..
1129 $ hg init explicit
1132 $ hg init explicit
1130 $ cd explicit
1133 $ cd explicit
1131 $ echo s = s > .hgsub
1134 $ echo s = s > .hgsub
1132 $ hg add .hgsub
1135 $ hg add .hgsub
1133 $ hg init s
1136 $ hg init s
1134 $ hg ci -m0
1137 $ hg ci -m0
1135 Adding with an explicit path in a subrepo adds the file
1138 Adding with an explicit path in a subrepo adds the file
1136 $ echo c1 > f1
1139 $ echo c1 > f1
1137 $ echo c2 > s/f2
1140 $ echo c2 > s/f2
1138 $ hg st -S
1141 $ hg st -S
1139 ? f1
1142 ? f1
1140 ? s/f2
1143 ? s/f2
1141 $ hg add s/f2
1144 $ hg add s/f2
1142 $ hg st -S
1145 $ hg st -S
1143 A s/f2
1146 A s/f2
1144 ? f1
1147 ? f1
1145 $ hg ci -R s -m0
1148 $ hg ci -R s -m0
1146 $ hg ci -Am1
1149 $ hg ci -Am1
1147 adding f1
1150 adding f1
1148 Adding with an explicit path in a subrepo with -S has the same behavior
1151 Adding with an explicit path in a subrepo with -S has the same behavior
1149 $ echo c3 > f3
1152 $ echo c3 > f3
1150 $ echo c4 > s/f4
1153 $ echo c4 > s/f4
1151 $ hg st -S
1154 $ hg st -S
1152 ? f3
1155 ? f3
1153 ? s/f4
1156 ? s/f4
1154 $ hg add -S s/f4
1157 $ hg add -S s/f4
1155 $ hg st -S
1158 $ hg st -S
1156 A s/f4
1159 A s/f4
1157 ? f3
1160 ? f3
1158 $ hg ci -R s -m1
1161 $ hg ci -R s -m1
1159 $ hg ci -Ama2
1162 $ hg ci -Ama2
1160 adding f3
1163 adding f3
1161 Adding without a path or pattern silently ignores subrepos
1164 Adding without a path or pattern silently ignores subrepos
1162 $ echo c5 > f5
1165 $ echo c5 > f5
1163 $ echo c6 > s/f6
1166 $ echo c6 > s/f6
1164 $ echo c7 > s/f7
1167 $ echo c7 > s/f7
1165 $ hg st -S
1168 $ hg st -S
1166 ? f5
1169 ? f5
1167 ? s/f6
1170 ? s/f6
1168 ? s/f7
1171 ? s/f7
1169 $ hg add
1172 $ hg add
1170 adding f5
1173 adding f5
1171 $ hg st -S
1174 $ hg st -S
1172 A f5
1175 A f5
1173 ? s/f6
1176 ? s/f6
1174 ? s/f7
1177 ? s/f7
1175 $ hg ci -R s -Am2
1178 $ hg ci -R s -Am2
1176 adding f6
1179 adding f6
1177 adding f7
1180 adding f7
1178 $ hg ci -m3
1181 $ hg ci -m3
1179 Adding without a path or pattern with -S also adds files in subrepos
1182 Adding without a path or pattern with -S also adds files in subrepos
1180 $ echo c8 > f8
1183 $ echo c8 > f8
1181 $ echo c9 > s/f9
1184 $ echo c9 > s/f9
1182 $ echo c10 > s/f10
1185 $ echo c10 > s/f10
1183 $ hg st -S
1186 $ hg st -S
1184 ? f8
1187 ? f8
1185 ? s/f10
1188 ? s/f10
1186 ? s/f9
1189 ? s/f9
1187 $ hg add -S
1190 $ hg add -S
1188 adding f8
1191 adding f8
1189 adding s/f10 (glob)
1192 adding s/f10 (glob)
1190 adding s/f9 (glob)
1193 adding s/f9 (glob)
1191 $ hg st -S
1194 $ hg st -S
1192 A f8
1195 A f8
1193 A s/f10
1196 A s/f10
1194 A s/f9
1197 A s/f9
1195 $ hg ci -R s -m3
1198 $ hg ci -R s -m3
1196 $ hg ci -m4
1199 $ hg ci -m4
1197 Adding with a pattern silently ignores subrepos
1200 Adding with a pattern silently ignores subrepos
1198 $ echo c11 > fm11
1201 $ echo c11 > fm11
1199 $ echo c12 > fn12
1202 $ echo c12 > fn12
1200 $ echo c13 > s/fm13
1203 $ echo c13 > s/fm13
1201 $ echo c14 > s/fn14
1204 $ echo c14 > s/fn14
1202 $ hg st -S
1205 $ hg st -S
1203 ? fm11
1206 ? fm11
1204 ? fn12
1207 ? fn12
1205 ? s/fm13
1208 ? s/fm13
1206 ? s/fn14
1209 ? s/fn14
1207 $ hg add 'glob:**fm*'
1210 $ hg add 'glob:**fm*'
1208 adding fm11
1211 adding fm11
1209 $ hg st -S
1212 $ hg st -S
1210 A fm11
1213 A fm11
1211 ? fn12
1214 ? fn12
1212 ? s/fm13
1215 ? s/fm13
1213 ? s/fn14
1216 ? s/fn14
1214 $ hg ci -R s -Am4
1217 $ hg ci -R s -Am4
1215 adding fm13
1218 adding fm13
1216 adding fn14
1219 adding fn14
1217 $ hg ci -Am5
1220 $ hg ci -Am5
1218 adding fn12
1221 adding fn12
1219 Adding with a pattern with -S also adds matches in subrepos
1222 Adding with a pattern with -S also adds matches in subrepos
1220 $ echo c15 > fm15
1223 $ echo c15 > fm15
1221 $ echo c16 > fn16
1224 $ echo c16 > fn16
1222 $ echo c17 > s/fm17
1225 $ echo c17 > s/fm17
1223 $ echo c18 > s/fn18
1226 $ echo c18 > s/fn18
1224 $ hg st -S
1227 $ hg st -S
1225 ? fm15
1228 ? fm15
1226 ? fn16
1229 ? fn16
1227 ? s/fm17
1230 ? s/fm17
1228 ? s/fn18
1231 ? s/fn18
1229 $ hg add -S 'glob:**fm*'
1232 $ hg add -S 'glob:**fm*'
1230 adding fm15
1233 adding fm15
1231 adding s/fm17 (glob)
1234 adding s/fm17 (glob)
1232 $ hg st -S
1235 $ hg st -S
1233 A fm15
1236 A fm15
1234 A s/fm17
1237 A s/fm17
1235 ? fn16
1238 ? fn16
1236 ? s/fn18
1239 ? s/fn18
1237 $ hg ci -R s -Am5
1240 $ hg ci -R s -Am5
1238 adding fn18
1241 adding fn18
1239 $ hg ci -Am6
1242 $ hg ci -Am6
1240 adding fn16
1243 adding fn16
1241
1244
1242 Test behavior of forget for explicit path in subrepo:
1245 Test behavior of forget for explicit path in subrepo:
1243 Forgetting an explicit path in a subrepo untracks the file
1246 Forgetting an explicit path in a subrepo untracks the file
1244 $ echo c19 > s/f19
1247 $ echo c19 > s/f19
1245 $ hg add s/f19
1248 $ hg add s/f19
1246 $ hg st -S
1249 $ hg st -S
1247 A s/f19
1250 A s/f19
1248 $ hg forget s/f19
1251 $ hg forget s/f19
1249 $ hg st -S
1252 $ hg st -S
1250 ? s/f19
1253 ? s/f19
1251 $ rm s/f19
1254 $ rm s/f19
1252 $ cd ..
1255 $ cd ..
1253
1256
1254 Courtesy phases synchronisation to publishing server does not block the push
1257 Courtesy phases synchronisation to publishing server does not block the push
1255 (issue3781)
1258 (issue3781)
1256
1259
1257 $ cp -r main issue3781
1260 $ cp -r main issue3781
1258 $ cp -r main issue3781-dest
1261 $ cp -r main issue3781-dest
1259 $ cd issue3781-dest/s
1262 $ cd issue3781-dest/s
1260 $ hg phase tip # show we have draft changeset
1263 $ hg phase tip # show we have draft changeset
1261 5: draft
1264 5: draft
1262 $ chmod a-w .hg/store/phaseroots # prevent phase push
1265 $ chmod a-w .hg/store/phaseroots # prevent phase push
1263 $ cd ../../issue3781
1266 $ cd ../../issue3781
1264 $ cat >> .hg/hgrc << EOF
1267 $ cat >> .hg/hgrc << EOF
1265 > [paths]
1268 > [paths]
1266 > default=../issue3781-dest/
1269 > default=../issue3781-dest/
1267 > EOF
1270 > EOF
1268 $ hg push
1271 $ hg push
1269 pushing to $TESTTMP/issue3781-dest (glob)
1272 pushing to $TESTTMP/issue3781-dest (glob)
1270 pushing subrepo s to $TESTTMP/issue3781-dest/s
1273 pushing subrepo s to $TESTTMP/issue3781-dest/s
1271 searching for changes
1274 searching for changes
1272 no changes found
1275 no changes found
1273 searching for changes
1276 searching for changes
1274 no changes found
1277 no changes found
1275 [1]
1278 [1]
1276 $ cd ..
1279 $ cd ..
1277
1280
1278 Test phase choice for newly created commit with "phases.subrepochecks"
1281 Test phase choice for newly created commit with "phases.subrepochecks"
1279 configuration
1282 configuration
1280
1283
1281 $ cd t
1284 $ cd t
1282 $ hg update -q -r 12
1285 $ hg update -q -r 12
1283
1286
1284 $ cat >> s/ss/.hg/hgrc <<EOF
1287 $ cat >> s/ss/.hg/hgrc <<EOF
1285 > [phases]
1288 > [phases]
1286 > new-commit = secret
1289 > new-commit = secret
1287 > EOF
1290 > EOF
1288 $ cat >> s/.hg/hgrc <<EOF
1291 $ cat >> s/.hg/hgrc <<EOF
1289 > [phases]
1292 > [phases]
1290 > new-commit = draft
1293 > new-commit = draft
1291 > EOF
1294 > EOF
1292 $ echo phasecheck1 >> s/ss/a
1295 $ echo phasecheck1 >> s/ss/a
1293 $ hg -R s commit -S --config phases.checksubrepos=abort -m phasecheck1
1296 $ hg -R s commit -S --config phases.checksubrepos=abort -m phasecheck1
1294 committing subrepository ss
1297 committing subrepository ss
1295 transaction abort!
1298 transaction abort!
1296 rollback completed
1299 rollback completed
1297 abort: can't commit in draft phase conflicting secret from subrepository ss
1300 abort: can't commit in draft phase conflicting secret from subrepository ss
1298 [255]
1301 [255]
1299 $ echo phasecheck2 >> s/ss/a
1302 $ echo phasecheck2 >> s/ss/a
1300 $ hg -R s commit -S --config phases.checksubrepos=ignore -m phasecheck2
1303 $ hg -R s commit -S --config phases.checksubrepos=ignore -m phasecheck2
1301 committing subrepository ss
1304 committing subrepository ss
1302 $ hg -R s/ss phase tip
1305 $ hg -R s/ss phase tip
1303 3: secret
1306 3: secret
1304 $ hg -R s phase tip
1307 $ hg -R s phase tip
1305 6: draft
1308 6: draft
1306 $ echo phasecheck3 >> s/ss/a
1309 $ echo phasecheck3 >> s/ss/a
1307 $ hg -R s commit -S -m phasecheck3
1310 $ hg -R s commit -S -m phasecheck3
1308 committing subrepository ss
1311 committing subrepository ss
1309 warning: changes are committed in secret phase from subrepository ss
1312 warning: changes are committed in secret phase from subrepository ss
1310 $ hg -R s/ss phase tip
1313 $ hg -R s/ss phase tip
1311 4: secret
1314 4: secret
1312 $ hg -R s phase tip
1315 $ hg -R s phase tip
1313 7: secret
1316 7: secret
1314
1317
1315 $ cat >> t/.hg/hgrc <<EOF
1318 $ cat >> t/.hg/hgrc <<EOF
1316 > [phases]
1319 > [phases]
1317 > new-commit = draft
1320 > new-commit = draft
1318 > EOF
1321 > EOF
1319 $ cat >> .hg/hgrc <<EOF
1322 $ cat >> .hg/hgrc <<EOF
1320 > [phases]
1323 > [phases]
1321 > new-commit = public
1324 > new-commit = public
1322 > EOF
1325 > EOF
1323 $ echo phasecheck4 >> s/ss/a
1326 $ echo phasecheck4 >> s/ss/a
1324 $ echo phasecheck4 >> t/t
1327 $ echo phasecheck4 >> t/t
1325 $ hg commit -S -m phasecheck4
1328 $ hg commit -S -m phasecheck4
1326 committing subrepository s
1329 committing subrepository s
1327 committing subrepository s/ss (glob)
1330 committing subrepository s/ss (glob)
1328 warning: changes are committed in secret phase from subrepository ss
1331 warning: changes are committed in secret phase from subrepository ss
1329 committing subrepository t
1332 committing subrepository t
1330 warning: changes are committed in secret phase from subrepository s
1333 warning: changes are committed in secret phase from subrepository s
1331 created new head
1334 created new head
1332 $ hg -R s/ss phase tip
1335 $ hg -R s/ss phase tip
1333 5: secret
1336 5: secret
1334 $ hg -R s phase tip
1337 $ hg -R s phase tip
1335 8: secret
1338 8: secret
1336 $ hg -R t phase tip
1339 $ hg -R t phase tip
1337 6: draft
1340 6: draft
1338 $ hg phase tip
1341 $ hg phase tip
1339 15: secret
1342 15: secret
1340
1343
1341 $ cd ..
1344 $ cd ..
1342
1345
1343
1346
1344 Test that commit --secret works on both repo and subrepo (issue4182)
1347 Test that commit --secret works on both repo and subrepo (issue4182)
1345
1348
1346 $ cd main
1349 $ cd main
1347 $ echo secret >> b
1350 $ echo secret >> b
1348 $ echo secret >> s/b
1351 $ echo secret >> s/b
1349 $ hg commit --secret --subrepo -m "secret"
1352 $ hg commit --secret --subrepo -m "secret"
1350 committing subrepository s
1353 committing subrepository s
1351 $ hg phase -r .
1354 $ hg phase -r .
1352 6: secret
1355 6: secret
1353 $ cd s
1356 $ cd s
1354 $ hg phase -r .
1357 $ hg phase -r .
1355 6: secret
1358 6: secret
1356 $ cd ../../
1359 $ cd ../../
1357
1360
1358 Test "subrepos" template keyword
1361 Test "subrepos" template keyword
1359
1362
1360 $ cd t
1363 $ cd t
1361 $ hg update -q 15
1364 $ hg update -q 15
1362 $ cat > .hgsub <<EOF
1365 $ cat > .hgsub <<EOF
1363 > s = s
1366 > s = s
1364 > EOF
1367 > EOF
1365 $ hg commit -m "16"
1368 $ hg commit -m "16"
1366 warning: changes are committed in secret phase from subrepository s
1369 warning: changes are committed in secret phase from subrepository s
1367
1370
1368 (addition of ".hgsub" itself)
1371 (addition of ".hgsub" itself)
1369
1372
1370 $ hg diff --nodates -c 1 .hgsubstate
1373 $ hg diff --nodates -c 1 .hgsubstate
1371 diff -r f7b1eb17ad24 -r 7cf8cfea66e4 .hgsubstate
1374 diff -r f7b1eb17ad24 -r 7cf8cfea66e4 .hgsubstate
1372 --- /dev/null
1375 --- /dev/null
1373 +++ b/.hgsubstate
1376 +++ b/.hgsubstate
1374 @@ -0,0 +1,1 @@
1377 @@ -0,0 +1,1 @@
1375 +e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1378 +e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1376 $ hg log -r 1 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1379 $ hg log -r 1 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1377 f7b1eb17ad24 000000000000
1380 f7b1eb17ad24 000000000000
1378 s
1381 s
1379
1382
1380 (modification of existing entry)
1383 (modification of existing entry)
1381
1384
1382 $ hg diff --nodates -c 2 .hgsubstate
1385 $ hg diff --nodates -c 2 .hgsubstate
1383 diff -r 7cf8cfea66e4 -r df30734270ae .hgsubstate
1386 diff -r 7cf8cfea66e4 -r df30734270ae .hgsubstate
1384 --- a/.hgsubstate
1387 --- a/.hgsubstate
1385 +++ b/.hgsubstate
1388 +++ b/.hgsubstate
1386 @@ -1,1 +1,1 @@
1389 @@ -1,1 +1,1 @@
1387 -e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1390 -e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1388 +dc73e2e6d2675eb2e41e33c205f4bdab4ea5111d s
1391 +dc73e2e6d2675eb2e41e33c205f4bdab4ea5111d s
1389 $ hg log -r 2 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1392 $ hg log -r 2 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1390 7cf8cfea66e4 000000000000
1393 7cf8cfea66e4 000000000000
1391 s
1394 s
1392
1395
1393 (addition of entry)
1396 (addition of entry)
1394
1397
1395 $ hg diff --nodates -c 5 .hgsubstate
1398 $ hg diff --nodates -c 5 .hgsubstate
1396 diff -r 7cf8cfea66e4 -r 1f14a2e2d3ec .hgsubstate
1399 diff -r 7cf8cfea66e4 -r 1f14a2e2d3ec .hgsubstate
1397 --- a/.hgsubstate
1400 --- a/.hgsubstate
1398 +++ b/.hgsubstate
1401 +++ b/.hgsubstate
1399 @@ -1,1 +1,2 @@
1402 @@ -1,1 +1,2 @@
1400 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1403 e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1401 +60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
1404 +60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
1402 $ hg log -r 5 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1405 $ hg log -r 5 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1403 7cf8cfea66e4 000000000000
1406 7cf8cfea66e4 000000000000
1404 t
1407 t
1405
1408
1406 (removal of existing entry)
1409 (removal of existing entry)
1407
1410
1408 $ hg diff --nodates -c 16 .hgsubstate
1411 $ hg diff --nodates -c 16 .hgsubstate
1409 diff -r 8bec38d2bd0b -r f2f70bc3d3c9 .hgsubstate
1412 diff -r 8bec38d2bd0b -r f2f70bc3d3c9 .hgsubstate
1410 --- a/.hgsubstate
1413 --- a/.hgsubstate
1411 +++ b/.hgsubstate
1414 +++ b/.hgsubstate
1412 @@ -1,2 +1,1 @@
1415 @@ -1,2 +1,1 @@
1413 0731af8ca9423976d3743119d0865097c07bdc1b s
1416 0731af8ca9423976d3743119d0865097c07bdc1b s
1414 -e202dc79b04c88a636ea8913d9182a1346d9b3dc t
1417 -e202dc79b04c88a636ea8913d9182a1346d9b3dc t
1415 $ hg log -r 16 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1418 $ hg log -r 16 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1416 8bec38d2bd0b 000000000000
1419 8bec38d2bd0b 000000000000
1417 t
1420 t
1418
1421
1419 (merging)
1422 (merging)
1420
1423
1421 $ hg diff --nodates -c 9 .hgsubstate
1424 $ hg diff --nodates -c 9 .hgsubstate
1422 diff -r f6affe3fbfaa -r f0d2028bf86d .hgsubstate
1425 diff -r f6affe3fbfaa -r f0d2028bf86d .hgsubstate
1423 --- a/.hgsubstate
1426 --- a/.hgsubstate
1424 +++ b/.hgsubstate
1427 +++ b/.hgsubstate
1425 @@ -1,1 +1,2 @@
1428 @@ -1,1 +1,2 @@
1426 fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1429 fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1427 +60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
1430 +60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
1428 $ hg log -r 9 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1431 $ hg log -r 9 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1429 f6affe3fbfaa 1f14a2e2d3ec
1432 f6affe3fbfaa 1f14a2e2d3ec
1430 t
1433 t
1431
1434
1432 (removal of ".hgsub" itself)
1435 (removal of ".hgsub" itself)
1433
1436
1434 $ hg diff --nodates -c 8 .hgsubstate
1437 $ hg diff --nodates -c 8 .hgsubstate
1435 diff -r f94576341bcf -r 96615c1dad2d .hgsubstate
1438 diff -r f94576341bcf -r 96615c1dad2d .hgsubstate
1436 --- a/.hgsubstate
1439 --- a/.hgsubstate
1437 +++ /dev/null
1440 +++ /dev/null
1438 @@ -1,2 +0,0 @@
1441 @@ -1,2 +0,0 @@
1439 -e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1442 -e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
1440 -7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4 t
1443 -7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4 t
1441 $ hg log -r 8 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1444 $ hg log -r 8 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
1442 f94576341bcf 000000000000
1445 f94576341bcf 000000000000
1443
1446
1444 Test that '[paths]' is configured correctly at subrepo creation
1447 Test that '[paths]' is configured correctly at subrepo creation
1445
1448
1446 $ cd $TESTTMP/tc
1449 $ cd $TESTTMP/tc
1447 $ cat > .hgsub <<EOF
1450 $ cat > .hgsub <<EOF
1448 > # to clear bogus subrepo path 'bogus=[boguspath'
1451 > # to clear bogus subrepo path 'bogus=[boguspath'
1449 > s = s
1452 > s = s
1450 > t = t
1453 > t = t
1451 > EOF
1454 > EOF
1452 $ hg update -q --clean null
1455 $ hg update -q --clean null
1453 $ rm -rf s t
1456 $ rm -rf s t
1454 $ cat >> .hg/hgrc <<EOF
1457 $ cat >> .hg/hgrc <<EOF
1455 > [paths]
1458 > [paths]
1456 > default-push = /foo/bar
1459 > default-push = /foo/bar
1457 > EOF
1460 > EOF
1458 $ hg update -q
1461 $ hg update -q
1459 $ cat s/.hg/hgrc
1462 $ cat s/.hg/hgrc
1460 [paths]
1463 [paths]
1461 default = $TESTTMP/t/s
1464 default = $TESTTMP/t/s
1462 default-push = /foo/bar/s
1465 default-push = /foo/bar/s
1463 $ cat s/ss/.hg/hgrc
1466 $ cat s/ss/.hg/hgrc
1464 [paths]
1467 [paths]
1465 default = $TESTTMP/t/s/ss
1468 default = $TESTTMP/t/s/ss
1466 default-push = /foo/bar/s/ss
1469 default-push = /foo/bar/s/ss
1467 $ cat t/.hg/hgrc
1470 $ cat t/.hg/hgrc
1468 [paths]
1471 [paths]
1469 default = $TESTTMP/t/t
1472 default = $TESTTMP/t/t
1470 default-push = /foo/bar/t
1473 default-push = /foo/bar/t
1471 $ cd ..
1474 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now