##// END OF EJS Templates
branchcache: add debug output whenever cache files use truncate...
Mads Kiilerich -
r23862:7aa14055 default
parent child Browse files
Show More
@@ -1,449 +1,451 b''
1 1 # branchmap.py - logic to computes, maintain and stores branchmap for local repo
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import bin, hex, nullid, nullrev
9 9 import encoding
10 10 import util
11 11 import time
12 12 from array import array
13 13 from struct import calcsize, pack, unpack
14 14
15 15 def _filename(repo):
16 16 """name of a branchcache file for a given repo or repoview"""
17 17 filename = "cache/branch2"
18 18 if repo.filtername:
19 19 filename = '%s-%s' % (filename, repo.filtername)
20 20 return filename
21 21
22 22 def read(repo):
23 23 try:
24 24 f = repo.opener(_filename(repo))
25 25 lines = f.read().split('\n')
26 26 f.close()
27 27 except (IOError, OSError):
28 28 return None
29 29
30 30 try:
31 31 cachekey = lines.pop(0).split(" ", 2)
32 32 last, lrev = cachekey[:2]
33 33 last, lrev = bin(last), int(lrev)
34 34 filteredhash = None
35 35 if len(cachekey) > 2:
36 36 filteredhash = bin(cachekey[2])
37 37 partial = branchcache(tipnode=last, tiprev=lrev,
38 38 filteredhash=filteredhash)
39 39 if not partial.validfor(repo):
40 40 # invalidate the cache
41 41 raise ValueError('tip differs')
42 42 for l in lines:
43 43 if not l:
44 44 continue
45 45 node, state, label = l.split(" ", 2)
46 46 if state not in 'oc':
47 47 raise ValueError('invalid branch state')
48 48 label = encoding.tolocal(label.strip())
49 49 if not node in repo:
50 50 raise ValueError('node %s does not exist' % node)
51 51 node = bin(node)
52 52 partial.setdefault(label, []).append(node)
53 53 if state == 'c':
54 54 partial._closednodes.add(node)
55 55 except KeyboardInterrupt:
56 56 raise
57 57 except Exception, inst:
58 58 if repo.ui.debugflag:
59 59 msg = 'invalid branchheads cache'
60 60 if repo.filtername is not None:
61 61 msg += ' (%s)' % repo.filtername
62 62 msg += ': %s\n'
63 63 repo.ui.debug(msg % inst)
64 64 partial = None
65 65 return partial
66 66
67 67 ### Nearest subset relation
68 68 # Nearest subset of filter X is a filter Y so that:
69 69 # * Y is included in X,
70 70 # * X - Y is as small as possible.
71 71 # This create and ordering used for branchmap purpose.
72 72 # the ordering may be partial
73 73 subsettable = {None: 'visible',
74 74 'visible': 'served',
75 75 'served': 'immutable',
76 76 'immutable': 'base'}
77 77
78 78 def updatecache(repo):
79 79 cl = repo.changelog
80 80 filtername = repo.filtername
81 81 partial = repo._branchcaches.get(filtername)
82 82
83 83 revs = []
84 84 if partial is None or not partial.validfor(repo):
85 85 partial = read(repo)
86 86 if partial is None:
87 87 subsetname = subsettable.get(filtername)
88 88 if subsetname is None:
89 89 partial = branchcache()
90 90 else:
91 91 subset = repo.filtered(subsetname)
92 92 partial = subset.branchmap().copy()
93 93 extrarevs = subset.changelog.filteredrevs - cl.filteredrevs
94 94 revs.extend(r for r in extrarevs if r <= partial.tiprev)
95 95 revs.extend(cl.revs(start=partial.tiprev + 1))
96 96 if revs:
97 97 partial.update(repo, revs)
98 98 partial.write(repo)
99 99 assert partial.validfor(repo), filtername
100 100 repo._branchcaches[repo.filtername] = partial
101 101
102 102 class branchcache(dict):
103 103 """A dict like object that hold branches heads cache.
104 104
105 105 This cache is used to avoid costly computations to determine all the
106 106 branch heads of a repo.
107 107
108 108 The cache is serialized on disk in the following format:
109 109
110 110 <tip hex node> <tip rev number> [optional filtered repo hex hash]
111 111 <branch head hex node> <open/closed state> <branch name>
112 112 <branch head hex node> <open/closed state> <branch name>
113 113 ...
114 114
115 115 The first line is used to check if the cache is still valid. If the
116 116 branch cache is for a filtered repo view, an optional third hash is
117 117 included that hashes the hashes of all filtered revisions.
118 118
119 119 The open/closed state is represented by a single letter 'o' or 'c'.
120 120 This field can be used to avoid changelog reads when determining if a
121 121 branch head closes a branch or not.
122 122 """
123 123
124 124 def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev,
125 125 filteredhash=None, closednodes=None):
126 126 super(branchcache, self).__init__(entries)
127 127 self.tipnode = tipnode
128 128 self.tiprev = tiprev
129 129 self.filteredhash = filteredhash
130 130 # closednodes is a set of nodes that close their branch. If the branch
131 131 # cache has been updated, it may contain nodes that are no longer
132 132 # heads.
133 133 if closednodes is None:
134 134 self._closednodes = set()
135 135 else:
136 136 self._closednodes = closednodes
137 137 self._revbranchcache = None
138 138
139 139 def _hashfiltered(self, repo):
140 140 """build hash of revision filtered in the current cache
141 141
142 142 Tracking tipnode and tiprev is not enough to ensure validity of the
143 143 cache as they do not help to distinct cache that ignored various
144 144 revision bellow tiprev.
145 145
146 146 To detect such difference, we build a cache of all ignored revisions.
147 147 """
148 148 cl = repo.changelog
149 149 if not cl.filteredrevs:
150 150 return None
151 151 key = None
152 152 revs = sorted(r for r in cl.filteredrevs if r <= self.tiprev)
153 153 if revs:
154 154 s = util.sha1()
155 155 for rev in revs:
156 156 s.update('%s;' % rev)
157 157 key = s.digest()
158 158 return key
159 159
160 160 def validfor(self, repo):
161 161 """Is the cache content valid regarding a repo
162 162
163 163 - False when cached tipnode is unknown or if we detect a strip.
164 164 - True when cache is up to date or a subset of current repo."""
165 165 try:
166 166 return ((self.tipnode == repo.changelog.node(self.tiprev))
167 167 and (self.filteredhash == self._hashfiltered(repo)))
168 168 except IndexError:
169 169 return False
170 170
171 171 def _branchtip(self, heads):
172 172 '''Return tuple with last open head in heads and false,
173 173 otherwise return last closed head and true.'''
174 174 tip = heads[-1]
175 175 closed = True
176 176 for h in reversed(heads):
177 177 if h not in self._closednodes:
178 178 tip = h
179 179 closed = False
180 180 break
181 181 return tip, closed
182 182
183 183 def branchtip(self, branch):
184 184 '''Return the tipmost open head on branch head, otherwise return the
185 185 tipmost closed head on branch.
186 186 Raise KeyError for unknown branch.'''
187 187 return self._branchtip(self[branch])[0]
188 188
189 189 def branchheads(self, branch, closed=False):
190 190 heads = self[branch]
191 191 if not closed:
192 192 heads = [h for h in heads if h not in self._closednodes]
193 193 return heads
194 194
195 195 def iterbranches(self):
196 196 for bn, heads in self.iteritems():
197 197 yield (bn, heads) + self._branchtip(heads)
198 198
199 199 def copy(self):
200 200 """return an deep copy of the branchcache object"""
201 201 return branchcache(self, self.tipnode, self.tiprev, self.filteredhash,
202 202 self._closednodes)
203 203
204 204 def write(self, repo):
205 205 try:
206 206 f = repo.opener(_filename(repo), "w", atomictemp=True)
207 207 cachekey = [hex(self.tipnode), str(self.tiprev)]
208 208 if self.filteredhash is not None:
209 209 cachekey.append(hex(self.filteredhash))
210 210 f.write(" ".join(cachekey) + '\n')
211 211 nodecount = 0
212 212 for label, nodes in sorted(self.iteritems()):
213 213 for node in nodes:
214 214 nodecount += 1
215 215 if node in self._closednodes:
216 216 state = 'c'
217 217 else:
218 218 state = 'o'
219 219 f.write("%s %s %s\n" % (hex(node), state,
220 220 encoding.fromlocal(label)))
221 221 f.close()
222 222 repo.ui.log('branchcache',
223 223 'wrote %s branch cache with %d labels and %d nodes\n',
224 224 repo.filtername, len(self), nodecount)
225 225 except (IOError, OSError, util.Abort), inst:
226 226 repo.ui.debug("couldn't write branch cache: %s\n" % inst)
227 227 # Abort may be raise by read only opener
228 228 pass
229 229 if self._revbranchcache:
230 230 self._revbranchcache.write(repo.unfiltered())
231 231 self._revbranchcache = None
232 232
233 233 def update(self, repo, revgen):
234 234 """Given a branchhead cache, self, that may have extra nodes or be
235 235 missing heads, and a generator of nodes that are strictly a superset of
236 236 heads missing, this function updates self to be correct.
237 237 """
238 238 starttime = time.time()
239 239 cl = repo.changelog
240 240 # collect new branch entries
241 241 newbranches = {}
242 242 urepo = repo.unfiltered()
243 243 self._revbranchcache = revbranchcache(urepo)
244 244 getbranchinfo = self._revbranchcache.branchinfo
245 245 ucl = urepo.changelog
246 246 for r in revgen:
247 247 branch, closesbranch = getbranchinfo(ucl, r)
248 248 newbranches.setdefault(branch, []).append(r)
249 249 if closesbranch:
250 250 self._closednodes.add(cl.node(r))
251 251
252 252 # fetch current topological heads to speed up filtering
253 253 topoheads = set(cl.headrevs())
254 254
255 255 # if older branchheads are reachable from new ones, they aren't
256 256 # really branchheads. Note checking parents is insufficient:
257 257 # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
258 258 for branch, newheadrevs in newbranches.iteritems():
259 259 bheads = self.setdefault(branch, [])
260 260 bheadset = set(cl.rev(node) for node in bheads)
261 261
262 262 # This have been tested True on all internal usage of this function.
263 263 # run it again in case of doubt
264 264 # assert not (set(bheadrevs) & set(newheadrevs))
265 265 newheadrevs.sort()
266 266 bheadset.update(newheadrevs)
267 267
268 268 # This prunes out two kinds of heads - heads that are superseded by
269 269 # a head in newheadrevs, and newheadrevs that are not heads because
270 270 # an existing head is their descendant.
271 271 uncertain = bheadset - topoheads
272 272 if uncertain:
273 273 floorrev = min(uncertain)
274 274 ancestors = set(cl.ancestors(newheadrevs, floorrev))
275 275 bheadset -= ancestors
276 276 bheadrevs = sorted(bheadset)
277 277 self[branch] = [cl.node(rev) for rev in bheadrevs]
278 278 tiprev = bheadrevs[-1]
279 279 if tiprev > self.tiprev:
280 280 self.tipnode = cl.node(tiprev)
281 281 self.tiprev = tiprev
282 282
283 283 if not self.validfor(repo):
284 284 # cache key are not valid anymore
285 285 self.tipnode = nullid
286 286 self.tiprev = nullrev
287 287 for heads in self.values():
288 288 tiprev = max(cl.rev(node) for node in heads)
289 289 if tiprev > self.tiprev:
290 290 self.tipnode = cl.node(tiprev)
291 291 self.tiprev = tiprev
292 292 self.filteredhash = self._hashfiltered(repo)
293 293
294 294 duration = time.time() - starttime
295 295 repo.ui.log('branchcache', 'updated %s branch cache in %.4f seconds\n',
296 296 repo.filtername, duration)
297 297
298 298 # Revision branch info cache
299 299
300 300 _rbcversion = '-v1'
301 301 _rbcnames = 'cache/rbc-names' + _rbcversion
302 302 _rbcrevs = 'cache/rbc-revs' + _rbcversion
303 303 # [4 byte hash prefix][4 byte branch name number with sign bit indicating open]
304 304 _rbcrecfmt = '>4sI'
305 305 _rbcrecsize = calcsize(_rbcrecfmt)
306 306 _rbcnodelen = 4
307 307 _rbcbranchidxmask = 0x7fffffff
308 308 _rbccloseflag = 0x80000000
309 309
310 310 class revbranchcache(object):
311 311 """Persistent cache, mapping from revision number to branch name and close.
312 312 This is a low level cache, independent of filtering.
313 313
314 314 Branch names are stored in rbc-names in internal encoding separated by 0.
315 315 rbc-names is append-only, and each branch name is only stored once and will
316 316 thus have a unique index.
317 317
318 318 The branch info for each revision is stored in rbc-revs as constant size
319 319 records. The whole file is read into memory, but it is only 'parsed' on
320 320 demand. The file is usually append-only but will be truncated if repo
321 321 modification is detected.
322 322 The record for each revision contains the first 4 bytes of the
323 323 corresponding node hash, and the record is only used if it still matches.
324 324 Even a completely trashed rbc-revs fill thus still give the right result
325 325 while converging towards full recovery ... assuming no incorrectly matching
326 326 node hashes.
327 327 The record also contains 4 bytes where 31 bits contains the index of the
328 328 branch and the last bit indicate that it is a branch close commit.
329 329 The usage pattern for rbc-revs is thus somewhat similar to 00changelog.i
330 330 and will grow with it but be 1/8th of its size.
331 331 """
332 332
333 333 def __init__(self, repo):
334 334 assert repo.filtername is None
335 335 self._names = [] # branch names in local encoding with static index
336 336 self._rbcrevs = array('c') # structs of type _rbcrecfmt
337 337 self._rbcsnameslen = 0
338 338 try:
339 339 bndata = repo.vfs.read(_rbcnames)
340 340 self._rbcsnameslen = len(bndata) # for verification before writing
341 341 self._names = [encoding.tolocal(bn) for bn in bndata.split('\0')]
342 342 except (IOError, OSError), inst:
343 343 repo.ui.debug("couldn't read revision branch cache names: %s\n" %
344 344 inst)
345 345 if self._names:
346 346 try:
347 347 data = repo.vfs.read(_rbcrevs)
348 348 self._rbcrevs.fromstring(data)
349 349 except (IOError, OSError), inst:
350 350 repo.ui.debug("couldn't read revision branch cache: %s\n" %
351 351 inst)
352 352 # remember number of good records on disk
353 353 self._rbcrevslen = min(len(self._rbcrevs) // _rbcrecsize,
354 354 len(repo.changelog))
355 355 if self._rbcrevslen == 0:
356 356 self._names = []
357 357 self._rbcnamescount = len(self._names) # number of good names on disk
358 358 self._namesreverse = dict((b, r) for r, b in enumerate(self._names))
359 359
360 360 def branchinfo(self, changelog, rev):
361 361 """Return branch name and close flag for rev, using and updating
362 362 persistent cache."""
363 363 rbcrevidx = rev * _rbcrecsize
364 364
365 365 # if requested rev is missing, add and populate all missing revs
366 366 if len(self._rbcrevs) < rbcrevidx + _rbcrecsize:
367 367 first = len(self._rbcrevs) // _rbcrecsize
368 368 self._rbcrevs.extend('\0' * (len(changelog) * _rbcrecsize -
369 369 len(self._rbcrevs)))
370 370 for r in xrange(first, len(changelog)):
371 371 self._branchinfo(changelog, r)
372 372
373 373 # fast path: extract data from cache, use it if node is matching
374 374 reponode = changelog.node(rev)[:_rbcnodelen]
375 375 cachenode, branchidx = unpack(
376 376 _rbcrecfmt, buffer(self._rbcrevs, rbcrevidx, _rbcrecsize))
377 377 close = bool(branchidx & _rbccloseflag)
378 378 if close:
379 379 branchidx &= _rbcbranchidxmask
380 380 if cachenode == reponode:
381 381 return self._names[branchidx], close
382 382 # fall back to slow path and make sure it will be written to disk
383 383 self._rbcrevslen = min(self._rbcrevslen, rev)
384 384 return self._branchinfo(changelog, rev)
385 385
386 386 def _branchinfo(self, changelog, rev):
387 387 """Retrieve branch info from changelog and update _rbcrevs"""
388 388 b, close = changelog.branchinfo(rev)
389 389 if b in self._namesreverse:
390 390 branchidx = self._namesreverse[b]
391 391 else:
392 392 branchidx = len(self._names)
393 393 self._names.append(b)
394 394 self._namesreverse[b] = branchidx
395 395 reponode = changelog.node(rev)
396 396 if close:
397 397 branchidx |= _rbccloseflag
398 398 rbcrevidx = rev * _rbcrecsize
399 399 rec = array('c')
400 400 rec.fromstring(pack(_rbcrecfmt, reponode, branchidx))
401 401 self._rbcrevs[rbcrevidx:rbcrevidx + _rbcrecsize] = rec
402 402 return b, close
403 403
404 404 def write(self, repo):
405 405 """Save branch cache if it is dirty."""
406 406 if self._rbcnamescount < len(self._names):
407 407 try:
408 408 if self._rbcnamescount != 0:
409 409 f = repo.vfs.open(_rbcnames, 'ab')
410 410 # The position after open(x, 'a') is implementation defined-
411 411 # see issue3543. SEEK_END was added in 2.5
412 412 f.seek(0, 2) #os.SEEK_END
413 413 if f.tell() == self._rbcsnameslen:
414 414 f.write('\0')
415 415 else:
416 416 f.close()
417 repo.ui.debug("%s changed - rewriting it\n" % _rbcnames)
417 418 self._rbcnamescount = 0
418 419 self._rbcrevslen = 0
419 420 if self._rbcnamescount == 0:
420 421 f = repo.vfs.open(_rbcnames, 'wb')
421 422 f.write('\0'.join(encoding.fromlocal(b)
422 423 for b in self._names[self._rbcnamescount:]))
423 424 self._rbcsnameslen = f.tell()
424 425 f.close()
425 426 except (IOError, OSError, util.Abort), inst:
426 427 repo.ui.debug("couldn't write revision branch cache names: "
427 428 "%s\n" % inst)
428 429 return
429 430 self._rbcnamescount = len(self._names)
430 431
431 432 start = self._rbcrevslen * _rbcrecsize
432 433 if start != len(self._rbcrevs):
433 434 self._rbcrevslen = min(len(repo.changelog),
434 435 len(self._rbcrevs) // _rbcrecsize)
435 436 try:
436 437 f = repo.vfs.open(_rbcrevs, 'ab')
437 438 # The position after open(x, 'a') is implementation defined-
438 439 # see issue3543. SEEK_END was added in 2.5
439 440 f.seek(0, 2) #os.SEEK_END
440 441 if f.tell() != start:
442 repo.ui.debug("truncating %s to %s\n" % (_rbcrevs, start))
441 443 f.seek(start)
442 444 f.truncate()
443 445 end = self._rbcrevslen * _rbcrecsize
444 446 f.write(self._rbcrevs[start:end])
445 447 f.close()
446 448 except (IOError, OSError, util.Abort), inst:
447 449 repo.ui.debug("couldn't write revision branch cache: %s\n" %
448 450 inst)
449 451 return
@@ -1,623 +1,626 b''
1 1 $ hg init a
2 2 $ cd a
3 3 $ echo 'root' >root
4 4 $ hg add root
5 5 $ hg commit -d '0 0' -m "Adding root node"
6 6
7 7 $ echo 'a' >a
8 8 $ hg add a
9 9 $ hg branch a
10 10 marked working directory as branch a
11 11 (branches are permanent and global, did you want a bookmark?)
12 12 $ hg commit -d '1 0' -m "Adding a branch"
13 13
14 14 $ hg branch q
15 15 marked working directory as branch q
16 16 (branches are permanent and global, did you want a bookmark?)
17 17 $ echo 'aa' >a
18 18 $ hg branch -C
19 19 reset working directory to branch a
20 20 $ hg commit -d '2 0' -m "Adding to a branch"
21 21
22 22 $ hg update -C 0
23 23 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
24 24 $ echo 'b' >b
25 25 $ hg add b
26 26 $ hg branch b
27 27 marked working directory as branch b
28 28 (branches are permanent and global, did you want a bookmark?)
29 29 $ hg commit -d '2 0' -m "Adding b branch"
30 30
31 31 $ echo 'bh1' >bh1
32 32 $ hg add bh1
33 33 $ hg commit -d '3 0' -m "Adding b branch head 1"
34 34
35 35 $ hg update -C 2
36 36 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
37 37 $ echo 'bh2' >bh2
38 38 $ hg add bh2
39 39 $ hg commit -d '4 0' -m "Adding b branch head 2"
40 40
41 41 $ echo 'c' >c
42 42 $ hg add c
43 43 $ hg branch c
44 44 marked working directory as branch c
45 45 (branches are permanent and global, did you want a bookmark?)
46 46 $ hg commit -d '5 0' -m "Adding c branch"
47 47
48 48 reserved names
49 49
50 50 $ hg branch tip
51 51 abort: the name 'tip' is reserved
52 52 [255]
53 53 $ hg branch null
54 54 abort: the name 'null' is reserved
55 55 [255]
56 56 $ hg branch .
57 57 abort: the name '.' is reserved
58 58 [255]
59 59
60 60 invalid characters
61 61
62 62 $ hg branch 'foo:bar'
63 63 abort: ':' cannot be used in a name
64 64 [255]
65 65
66 66 $ hg branch 'foo
67 67 > bar'
68 68 abort: '\n' cannot be used in a name
69 69 [255]
70 70
71 71 trailing or leading spaces should be stripped before testing duplicates
72 72
73 73 $ hg branch 'b '
74 74 abort: a branch of the same name already exists
75 75 (use 'hg update' to switch to it)
76 76 [255]
77 77
78 78 $ hg branch ' b'
79 79 abort: a branch of the same name already exists
80 80 (use 'hg update' to switch to it)
81 81 [255]
82 82
83 83 verify update will accept invalid legacy branch names
84 84
85 85 $ hg init test-invalid-branch-name
86 86 $ cd test-invalid-branch-name
87 87 $ hg pull -u "$TESTDIR"/bundles/test-invalid-branch-name.hg
88 88 pulling from *test-invalid-branch-name.hg (glob)
89 89 requesting all changes
90 90 adding changesets
91 91 adding manifests
92 92 adding file changes
93 93 added 3 changesets with 3 changes to 2 files
94 94 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
95 95
96 96 $ hg update '"colon:test"'
97 97 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
98 98 $ cd ..
99 99
100 100 $ echo 'd' >d
101 101 $ hg add d
102 102 $ hg branch 'a branch name much longer than the default justification used by branches'
103 103 marked working directory as branch a branch name much longer than the default justification used by branches
104 104 (branches are permanent and global, did you want a bookmark?)
105 105 $ hg commit -d '6 0' -m "Adding d branch"
106 106
107 107 $ hg branches
108 108 a branch name much longer than the default justification used by branches 7:10ff5895aa57
109 109 b 4:aee39cd168d0
110 110 c 6:589736a22561 (inactive)
111 111 a 5:d8cbc61dbaa6 (inactive)
112 112 default 0:19709c5a4e75 (inactive)
113 113
114 114 -------
115 115
116 116 $ hg branches -a
117 117 a branch name much longer than the default justification used by branches 7:10ff5895aa57
118 118 b 4:aee39cd168d0
119 119
120 120 --- Branch a
121 121
122 122 $ hg log -b a
123 123 changeset: 5:d8cbc61dbaa6
124 124 branch: a
125 125 parent: 2:881fe2b92ad0
126 126 user: test
127 127 date: Thu Jan 01 00:00:04 1970 +0000
128 128 summary: Adding b branch head 2
129 129
130 130 changeset: 2:881fe2b92ad0
131 131 branch: a
132 132 user: test
133 133 date: Thu Jan 01 00:00:02 1970 +0000
134 134 summary: Adding to a branch
135 135
136 136 changeset: 1:dd6b440dd85a
137 137 branch: a
138 138 user: test
139 139 date: Thu Jan 01 00:00:01 1970 +0000
140 140 summary: Adding a branch
141 141
142 142
143 143 ---- Branch b
144 144
145 145 $ hg log -b b
146 146 changeset: 4:aee39cd168d0
147 147 branch: b
148 148 user: test
149 149 date: Thu Jan 01 00:00:03 1970 +0000
150 150 summary: Adding b branch head 1
151 151
152 152 changeset: 3:ac22033332d1
153 153 branch: b
154 154 parent: 0:19709c5a4e75
155 155 user: test
156 156 date: Thu Jan 01 00:00:02 1970 +0000
157 157 summary: Adding b branch
158 158
159 159
160 160 ---- going to test branch closing
161 161
162 162 $ hg branches
163 163 a branch name much longer than the default justification used by branches 7:10ff5895aa57
164 164 b 4:aee39cd168d0
165 165 c 6:589736a22561 (inactive)
166 166 a 5:d8cbc61dbaa6 (inactive)
167 167 default 0:19709c5a4e75 (inactive)
168 168 $ hg up -C b
169 169 2 files updated, 0 files merged, 4 files removed, 0 files unresolved
170 170 $ echo 'xxx1' >> b
171 171 $ hg commit -d '7 0' -m 'adding cset to branch b'
172 172 $ hg up -C aee39cd168d0
173 173 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
174 174 $ echo 'xxx2' >> b
175 175 $ hg commit -d '8 0' -m 'adding head to branch b'
176 176 created new head
177 177 $ echo 'xxx3' >> b
178 178 $ hg commit -d '9 0' -m 'adding another cset to branch b'
179 179 $ hg branches
180 180 b 10:bfbe841b666e
181 181 a branch name much longer than the default justification used by branches 7:10ff5895aa57
182 182 c 6:589736a22561 (inactive)
183 183 a 5:d8cbc61dbaa6 (inactive)
184 184 default 0:19709c5a4e75 (inactive)
185 185 $ hg heads --closed
186 186 changeset: 10:bfbe841b666e
187 187 branch: b
188 188 tag: tip
189 189 user: test
190 190 date: Thu Jan 01 00:00:09 1970 +0000
191 191 summary: adding another cset to branch b
192 192
193 193 changeset: 8:eebb944467c9
194 194 branch: b
195 195 parent: 4:aee39cd168d0
196 196 user: test
197 197 date: Thu Jan 01 00:00:07 1970 +0000
198 198 summary: adding cset to branch b
199 199
200 200 changeset: 7:10ff5895aa57
201 201 branch: a branch name much longer than the default justification used by branches
202 202 user: test
203 203 date: Thu Jan 01 00:00:06 1970 +0000
204 204 summary: Adding d branch
205 205
206 206 changeset: 6:589736a22561
207 207 branch: c
208 208 user: test
209 209 date: Thu Jan 01 00:00:05 1970 +0000
210 210 summary: Adding c branch
211 211
212 212 changeset: 5:d8cbc61dbaa6
213 213 branch: a
214 214 parent: 2:881fe2b92ad0
215 215 user: test
216 216 date: Thu Jan 01 00:00:04 1970 +0000
217 217 summary: Adding b branch head 2
218 218
219 219 changeset: 0:19709c5a4e75
220 220 user: test
221 221 date: Thu Jan 01 00:00:00 1970 +0000
222 222 summary: Adding root node
223 223
224 224 $ hg heads
225 225 changeset: 10:bfbe841b666e
226 226 branch: b
227 227 tag: tip
228 228 user: test
229 229 date: Thu Jan 01 00:00:09 1970 +0000
230 230 summary: adding another cset to branch b
231 231
232 232 changeset: 8:eebb944467c9
233 233 branch: b
234 234 parent: 4:aee39cd168d0
235 235 user: test
236 236 date: Thu Jan 01 00:00:07 1970 +0000
237 237 summary: adding cset to branch b
238 238
239 239 changeset: 7:10ff5895aa57
240 240 branch: a branch name much longer than the default justification used by branches
241 241 user: test
242 242 date: Thu Jan 01 00:00:06 1970 +0000
243 243 summary: Adding d branch
244 244
245 245 changeset: 6:589736a22561
246 246 branch: c
247 247 user: test
248 248 date: Thu Jan 01 00:00:05 1970 +0000
249 249 summary: Adding c branch
250 250
251 251 changeset: 5:d8cbc61dbaa6
252 252 branch: a
253 253 parent: 2:881fe2b92ad0
254 254 user: test
255 255 date: Thu Jan 01 00:00:04 1970 +0000
256 256 summary: Adding b branch head 2
257 257
258 258 changeset: 0:19709c5a4e75
259 259 user: test
260 260 date: Thu Jan 01 00:00:00 1970 +0000
261 261 summary: Adding root node
262 262
263 263 $ hg commit -d '9 0' --close-branch -m 'prune bad branch'
264 264 $ hg branches -a
265 265 b 8:eebb944467c9
266 266 a branch name much longer than the default justification used by branches 7:10ff5895aa57
267 267 $ hg up -C b
268 268 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
269 269 $ hg commit -d '9 0' --close-branch -m 'close this part branch too'
270 270 $ hg commit -d '9 0' --close-branch -m 're-closing this branch'
271 271 abort: can only close branch heads
272 272 [255]
273 273
274 274 $ hg log -r tip --debug
275 275 changeset: 12:e3d49c0575d8fc2cb1cd6859c747c14f5f6d499f
276 276 branch: b
277 277 tag: tip
278 278 phase: draft
279 279 parent: 8:eebb944467c9fb9651ed232aeaf31b3c0a7fc6c1
280 280 parent: -1:0000000000000000000000000000000000000000
281 281 manifest: 8:6f9ed32d2b310e391a4f107d5f0f071df785bfee
282 282 user: test
283 283 date: Thu Jan 01 00:00:09 1970 +0000
284 284 extra: branch=b
285 285 extra: close=1
286 286 description:
287 287 close this part branch too
288 288
289 289
290 290 --- b branch should be inactive
291 291
292 292 $ hg branches
293 293 a branch name much longer than the default justification used by branches 7:10ff5895aa57
294 294 c 6:589736a22561 (inactive)
295 295 a 5:d8cbc61dbaa6 (inactive)
296 296 default 0:19709c5a4e75 (inactive)
297 297 $ hg branches -c
298 298 a branch name much longer than the default justification used by branches 7:10ff5895aa57
299 299 b 12:e3d49c0575d8 (closed)
300 300 c 6:589736a22561 (inactive)
301 301 a 5:d8cbc61dbaa6 (inactive)
302 302 default 0:19709c5a4e75 (inactive)
303 303 $ hg branches -a
304 304 a branch name much longer than the default justification used by branches 7:10ff5895aa57
305 305 $ hg branches -q
306 306 a branch name much longer than the default justification used by branches
307 307 c
308 308 a
309 309 default
310 310 $ hg heads b
311 311 no open branch heads found on branches b
312 312 [1]
313 313 $ hg heads --closed b
314 314 changeset: 12:e3d49c0575d8
315 315 branch: b
316 316 tag: tip
317 317 parent: 8:eebb944467c9
318 318 user: test
319 319 date: Thu Jan 01 00:00:09 1970 +0000
320 320 summary: close this part branch too
321 321
322 322 changeset: 11:d3f163457ebf
323 323 branch: b
324 324 user: test
325 325 date: Thu Jan 01 00:00:09 1970 +0000
326 326 summary: prune bad branch
327 327
328 328 $ echo 'xxx4' >> b
329 329 $ hg commit -d '9 0' -m 'reopen branch with a change'
330 330 reopening closed branch head 12
331 331
332 332 --- branch b is back in action
333 333
334 334 $ hg branches -a
335 335 b 13:e23b5505d1ad
336 336 a branch name much longer than the default justification used by branches 7:10ff5895aa57
337 337
338 338 ---- test heads listings
339 339
340 340 $ hg heads
341 341 changeset: 13:e23b5505d1ad
342 342 branch: b
343 343 tag: tip
344 344 user: test
345 345 date: Thu Jan 01 00:00:09 1970 +0000
346 346 summary: reopen branch with a change
347 347
348 348 changeset: 7:10ff5895aa57
349 349 branch: a branch name much longer than the default justification used by branches
350 350 user: test
351 351 date: Thu Jan 01 00:00:06 1970 +0000
352 352 summary: Adding d branch
353 353
354 354 changeset: 6:589736a22561
355 355 branch: c
356 356 user: test
357 357 date: Thu Jan 01 00:00:05 1970 +0000
358 358 summary: Adding c branch
359 359
360 360 changeset: 5:d8cbc61dbaa6
361 361 branch: a
362 362 parent: 2:881fe2b92ad0
363 363 user: test
364 364 date: Thu Jan 01 00:00:04 1970 +0000
365 365 summary: Adding b branch head 2
366 366
367 367 changeset: 0:19709c5a4e75
368 368 user: test
369 369 date: Thu Jan 01 00:00:00 1970 +0000
370 370 summary: Adding root node
371 371
372 372
373 373 branch default
374 374
375 375 $ hg heads default
376 376 changeset: 0:19709c5a4e75
377 377 user: test
378 378 date: Thu Jan 01 00:00:00 1970 +0000
379 379 summary: Adding root node
380 380
381 381
382 382 branch a
383 383
384 384 $ hg heads a
385 385 changeset: 5:d8cbc61dbaa6
386 386 branch: a
387 387 parent: 2:881fe2b92ad0
388 388 user: test
389 389 date: Thu Jan 01 00:00:04 1970 +0000
390 390 summary: Adding b branch head 2
391 391
392 392 $ hg heads --active a
393 393 no open branch heads found on branches a
394 394 [1]
395 395
396 396 branch b
397 397
398 398 $ hg heads b
399 399 changeset: 13:e23b5505d1ad
400 400 branch: b
401 401 tag: tip
402 402 user: test
403 403 date: Thu Jan 01 00:00:09 1970 +0000
404 404 summary: reopen branch with a change
405 405
406 406 $ hg heads --closed b
407 407 changeset: 13:e23b5505d1ad
408 408 branch: b
409 409 tag: tip
410 410 user: test
411 411 date: Thu Jan 01 00:00:09 1970 +0000
412 412 summary: reopen branch with a change
413 413
414 414 changeset: 11:d3f163457ebf
415 415 branch: b
416 416 user: test
417 417 date: Thu Jan 01 00:00:09 1970 +0000
418 418 summary: prune bad branch
419 419
420 420 default branch colors:
421 421
422 422 $ cat <<EOF >> $HGRCPATH
423 423 > [extensions]
424 424 > color =
425 425 > [color]
426 426 > mode = ansi
427 427 > EOF
428 428
429 429 $ hg up -C c
430 430 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
431 431 $ hg commit -d '9 0' --close-branch -m 'reclosing this branch'
432 432 $ hg up -C b
433 433 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
434 434 $ hg branches --color=always
435 435 \x1b[0;32mb\x1b[0m\x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
436 436 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;33m 7:10ff5895aa57\x1b[0m (esc)
437 437 \x1b[0;0ma\x1b[0m\x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
438 438 \x1b[0;0mdefault\x1b[0m\x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
439 439
440 440 default closed branch color:
441 441
442 442 $ hg branches --color=always --closed
443 443 \x1b[0;32mb\x1b[0m\x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
444 444 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;33m 7:10ff5895aa57\x1b[0m (esc)
445 445 \x1b[0;30;1mc\x1b[0m\x1b[0;33m 14:f894c25619d3\x1b[0m (closed) (esc)
446 446 \x1b[0;0ma\x1b[0m\x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
447 447 \x1b[0;0mdefault\x1b[0m\x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
448 448
449 449 $ cat <<EOF >> $HGRCPATH
450 450 > [extensions]
451 451 > color =
452 452 > [color]
453 453 > branches.active = green
454 454 > branches.closed = blue
455 455 > branches.current = red
456 456 > branches.inactive = magenta
457 457 > log.changeset = cyan
458 458 > EOF
459 459
460 460 custom branch colors:
461 461
462 462 $ hg branches --color=always
463 463 \x1b[0;31mb\x1b[0m\x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
464 464 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;36m 7:10ff5895aa57\x1b[0m (esc)
465 465 \x1b[0;35ma\x1b[0m\x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
466 466 \x1b[0;35mdefault\x1b[0m\x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
467 467
468 468 custom closed branch color:
469 469
470 470 $ hg branches --color=always --closed
471 471 \x1b[0;31mb\x1b[0m\x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
472 472 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;36m 7:10ff5895aa57\x1b[0m (esc)
473 473 \x1b[0;34mc\x1b[0m\x1b[0;36m 14:f894c25619d3\x1b[0m (closed) (esc)
474 474 \x1b[0;35ma\x1b[0m\x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
475 475 \x1b[0;35mdefault\x1b[0m\x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
476 476
477 477 template output:
478 478
479 479 $ hg branches -Tjson --closed
480 480 [
481 481 {
482 482 "active": true,
483 483 "branch": "b",
484 484 "closed": false,
485 485 "current": true,
486 486 "node": "e23b5505d1ad24aab6f84fd8c7cb8cd8e5e93be0",
487 487 "rev": 13
488 488 },
489 489 {
490 490 "active": true,
491 491 "branch": "a branch name much longer than the default justification used by branches",
492 492 "closed": false,
493 493 "current": false,
494 494 "node": "10ff5895aa5793bd378da574af8cec8ea408d831",
495 495 "rev": 7
496 496 },
497 497 {
498 498 "active": false,
499 499 "branch": "c",
500 500 "closed": true,
501 501 "current": false,
502 502 "node": "f894c25619d3f1484639d81be950e0a07bc6f1f6",
503 503 "rev": 14
504 504 },
505 505 {
506 506 "active": false,
507 507 "branch": "a",
508 508 "closed": false,
509 509 "current": false,
510 510 "node": "d8cbc61dbaa6dc817175d1e301eecb863f280832",
511 511 "rev": 5
512 512 },
513 513 {
514 514 "active": false,
515 515 "branch": "default",
516 516 "closed": false,
517 517 "current": false,
518 518 "node": "19709c5a4e75bf938f8e349aff97438539bb729e",
519 519 "rev": 0
520 520 }
521 521 ]
522 522
523 523
524 524 Tests of revision branch name caching
525 525
526 526 We rev branch cache is updated automatically. In these tests we use a trick to
527 527 trigger rebuilds. We remove the branch head cache and run 'hg head' to cause a
528 528 rebuild that also will populate the rev branch cache.
529 529
530 530 revision branch cache is created when building the branch head cache
531 531 $ rm -rf .hg/cache; hg head a -T '{rev}\n'
532 532 5
533 533 $ f --hexdump --size .hg/cache/rbc-*
534 534 .hg/cache/rbc-names-v1: size=87
535 535 0000: 64 65 66 61 75 6c 74 00 61 00 62 00 63 00 61 20 |default.a.b.c.a |
536 536 0010: 62 72 61 6e 63 68 20 6e 61 6d 65 20 6d 75 63 68 |branch name much|
537 537 0020: 20 6c 6f 6e 67 65 72 20 74 68 61 6e 20 74 68 65 | longer than the|
538 538 0030: 20 64 65 66 61 75 6c 74 20 6a 75 73 74 69 66 69 | default justifi|
539 539 0040: 63 61 74 69 6f 6e 20 75 73 65 64 20 62 79 20 62 |cation used by b|
540 540 0050: 72 61 6e 63 68 65 73 |ranches|
541 541 .hg/cache/rbc-revs-v1: size=120
542 542 0000: 19 70 9c 5a 00 00 00 00 dd 6b 44 0d 00 00 00 01 |.p.Z.....kD.....|
543 543 0010: 88 1f e2 b9 00 00 00 01 ac 22 03 33 00 00 00 02 |.........".3....|
544 544 0020: ae e3 9c d1 00 00 00 02 d8 cb c6 1d 00 00 00 01 |................|
545 545 0030: 58 97 36 a2 00 00 00 03 10 ff 58 95 00 00 00 04 |X.6.......X.....|
546 546 0040: ee bb 94 44 00 00 00 02 5f 40 61 bb 00 00 00 02 |...D...._@a.....|
547 547 0050: bf be 84 1b 00 00 00 02 d3 f1 63 45 80 00 00 02 |..........cE....|
548 548 0060: e3 d4 9c 05 80 00 00 02 e2 3b 55 05 00 00 00 02 |.........;U.....|
549 549 0070: f8 94 c2 56 80 00 00 03 |...V....|
550 550 recovery from invalid cache revs file with trailing data
551 551 $ echo >> .hg/cache/rbc-revs-v1
552 552 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
553 truncating cache/rbc-revs-v1 to 120
553 554 5
554 555 $ f --size .hg/cache/rbc-revs*
555 556 .hg/cache/rbc-revs-v1: size=120
556 557 recovery from invalid cache file with partial last record
557 558 $ mv .hg/cache/rbc-revs-v1 .
558 559 $ f -qDB 119 rbc-revs-v1 > .hg/cache/rbc-revs-v1
559 560 $ f --size .hg/cache/rbc-revs*
560 561 .hg/cache/rbc-revs-v1: size=119
561 562 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
563 truncating cache/rbc-revs-v1 to 112
562 564 5
563 565 $ f --size .hg/cache/rbc-revs*
564 566 .hg/cache/rbc-revs-v1: size=120
565 567 recovery from invalid cache file with missing record - no truncation
566 568 $ mv .hg/cache/rbc-revs-v1 .
567 569 $ f -qDB 112 rbc-revs-v1 > .hg/cache/rbc-revs-v1
568 570 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
569 571 5
570 572 $ f --size .hg/cache/rbc-revs*
571 573 .hg/cache/rbc-revs-v1: size=120
572 574 recovery from invalid cache file with some bad records
573 575 $ mv .hg/cache/rbc-revs-v1 .
574 576 $ f -qDB 8 rbc-revs-v1 > .hg/cache/rbc-revs-v1
575 577 $ f --size .hg/cache/rbc-revs*
576 578 .hg/cache/rbc-revs-v1: size=8
577 579 $ f -qDB 112 rbc-revs-v1 >> .hg/cache/rbc-revs-v1
578 580 $ f --size .hg/cache/rbc-revs*
579 581 .hg/cache/rbc-revs-v1: size=120
580 582 $ hg log -r 'branch(.)' -T '{rev} '
581 583 3 4 8 9 10 11 12 13 (no-eol)
582 584 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
585 truncating cache/rbc-revs-v1 to 8
583 586 5
584 587 $ f --size --hexdump --bytes=16 .hg/cache/rbc-revs*
585 588 .hg/cache/rbc-revs-v1: size=120
586 589 0000: 19 70 9c 5a 00 00 00 00 dd 6b 44 0d 00 00 00 01 |.p.Z.....kD.....|
587 590 cache is updated when committing
588 591 $ hg branch i-will-regret-this
589 592 marked working directory as branch i-will-regret-this
590 593 (branches are permanent and global, did you want a bookmark?)
591 594 $ hg ci -m regrets
592 595 $ f --size .hg/cache/rbc-*
593 596 .hg/cache/rbc-names-v1: size=106
594 597 .hg/cache/rbc-revs-v1: size=128
595 598 update after rollback - the cache will be correct but rbc-names will will still
596 599 contain the branch name even though it no longer is used
597 600 $ hg up -qr '.^'
598 601 $ hg rollback -qf
599 602 $ f --size --hexdump .hg/cache/rbc-*
600 603 .hg/cache/rbc-names-v1: size=106
601 604 0000: 64 65 66 61 75 6c 74 00 61 00 62 00 63 00 61 20 |default.a.b.c.a |
602 605 0010: 62 72 61 6e 63 68 20 6e 61 6d 65 20 6d 75 63 68 |branch name much|
603 606 0020: 20 6c 6f 6e 67 65 72 20 74 68 61 6e 20 74 68 65 | longer than the|
604 607 0030: 20 64 65 66 61 75 6c 74 20 6a 75 73 74 69 66 69 | default justifi|
605 608 0040: 63 61 74 69 6f 6e 20 75 73 65 64 20 62 79 20 62 |cation used by b|
606 609 0050: 72 61 6e 63 68 65 73 00 69 2d 77 69 6c 6c 2d 72 |ranches.i-will-r|
607 610 0060: 65 67 72 65 74 2d 74 68 69 73 |egret-this|
608 611 .hg/cache/rbc-revs-v1: size=120
609 612 0000: 19 70 9c 5a 00 00 00 00 dd 6b 44 0d 00 00 00 01 |.p.Z.....kD.....|
610 613 0010: 88 1f e2 b9 00 00 00 01 ac 22 03 33 00 00 00 02 |.........".3....|
611 614 0020: ae e3 9c d1 00 00 00 02 d8 cb c6 1d 00 00 00 01 |................|
612 615 0030: 58 97 36 a2 00 00 00 03 10 ff 58 95 00 00 00 04 |X.6.......X.....|
613 616 0040: ee bb 94 44 00 00 00 02 5f 40 61 bb 00 00 00 02 |...D...._@a.....|
614 617 0050: bf be 84 1b 00 00 00 02 d3 f1 63 45 80 00 00 02 |..........cE....|
615 618 0060: e3 d4 9c 05 80 00 00 02 e2 3b 55 05 00 00 00 02 |.........;U.....|
616 619 0070: f8 94 c2 56 80 00 00 03 |...V....|
617 620 cache is updated/truncated when stripping - it is thus very hard to get in a
618 621 situation where the cache is out of sync and the hash check detects it
619 622 $ hg --config extensions.strip= strip -r tip --nob
620 623 $ f --size .hg/cache/rbc-revs*
621 624 .hg/cache/rbc-revs-v1: size=112
622 625
623 626 $ cd ..
@@ -1,326 +1,327 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extensions]
3 3 > rebase=
4 4 >
5 5 > [phases]
6 6 > publish=False
7 7 >
8 8 > [alias]
9 9 > tglog = log -G --template "{rev}:{phase} '{desc}' {branches} {bookmarks}\n"
10 10 > EOF
11 11
12 12 $ hg init a
13 13 $ cd a
14 14 $ echo c1 >common
15 15 $ hg add common
16 16 $ hg ci -m C1
17 17
18 18 $ echo c2 >>common
19 19 $ hg ci -m C2
20 20
21 21 $ echo c3 >>common
22 22 $ hg ci -m C3
23 23
24 24 $ hg up -q -C 1
25 25
26 26 $ echo l1 >>extra
27 27 $ hg add extra
28 28 $ hg ci -m L1
29 29 created new head
30 30
31 31 $ sed -e 's/c2/l2/' common > common.new
32 32 $ mv common.new common
33 33 $ hg ci -m L2
34 34
35 35 $ echo l3 >> extra2
36 36 $ hg add extra2
37 37 $ hg ci -m L3
38 38 $ hg bookmark mybook
39 39
40 40 $ hg phase --force --secret 4
41 41
42 42 $ hg tglog
43 43 @ 5:secret 'L3' mybook
44 44 |
45 45 o 4:secret 'L2'
46 46 |
47 47 o 3:draft 'L1'
48 48 |
49 49 | o 2:draft 'C3'
50 50 |/
51 51 o 1:draft 'C2'
52 52 |
53 53 o 0:draft 'C1'
54 54
55 55 Try to call --continue:
56 56
57 57 $ hg rebase --continue
58 58 abort: no rebase in progress
59 59 [255]
60 60
61 61 Conflicting rebase:
62 62
63 63 $ hg rebase -s 3 -d 2
64 64 rebasing 3:3163e20567cc "L1"
65 65 rebasing 4:46f0b057b5c0 "L2"
66 66 merging common
67 67 warning: conflicts during merge.
68 68 merging common incomplete! (edit conflicts, then use 'hg resolve --mark')
69 69 unresolved conflicts (see hg resolve, then hg rebase --continue)
70 70 [1]
71 71
72 72 Try to continue without solving the conflict:
73 73
74 74 $ hg rebase --continue
75 75 already rebased 3:3163e20567cc "L1" as 3e046f2ecedb
76 76 rebasing 4:46f0b057b5c0 "L2"
77 77 abort: unresolved merge conflicts (see hg help resolve)
78 78 [255]
79 79
80 80 Conclude rebase:
81 81
82 82 $ echo 'resolved merge' >common
83 83 $ hg resolve -m common
84 84 (no more unresolved files)
85 85 $ hg rebase --continue
86 86 already rebased 3:3163e20567cc "L1" as 3e046f2ecedb
87 87 rebasing 4:46f0b057b5c0 "L2"
88 88 rebasing 5:8029388f38dc "L3" (mybook)
89 89 saved backup bundle to $TESTTMP/a/.hg/strip-backup/3163e20567cc-5ca4656e-backup.hg (glob)
90 90
91 91 $ hg tglog
92 92 @ 5:secret 'L3' mybook
93 93 |
94 94 o 4:secret 'L2'
95 95 |
96 96 o 3:draft 'L1'
97 97 |
98 98 o 2:draft 'C3'
99 99 |
100 100 o 1:draft 'C2'
101 101 |
102 102 o 0:draft 'C1'
103 103
104 104 Check correctness:
105 105
106 106 $ hg cat -r 0 common
107 107 c1
108 108
109 109 $ hg cat -r 1 common
110 110 c1
111 111 c2
112 112
113 113 $ hg cat -r 2 common
114 114 c1
115 115 c2
116 116 c3
117 117
118 118 $ hg cat -r 3 common
119 119 c1
120 120 c2
121 121 c3
122 122
123 123 $ hg cat -r 4 common
124 124 resolved merge
125 125
126 126 $ hg cat -r 5 common
127 127 resolved merge
128 128
129 129 Bookmark stays active after --continue
130 130 $ hg bookmarks
131 131 * mybook 5:d67b21408fc0
132 132
133 133 $ cd ..
134 134
135 135 Check that the right ancestors is used while rebasing a merge (issue4041)
136 136
137 137 $ hg clone "$TESTDIR/bundles/issue4041.hg" issue4041
138 138 requesting all changes
139 139 adding changesets
140 140 adding manifests
141 141 adding file changes
142 142 added 11 changesets with 8 changes to 3 files (+1 heads)
143 143 updating to branch default
144 144 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
145 145 $ cd issue4041
146 146 $ hg log -G
147 147 o changeset: 10:2f2496ddf49d
148 148 |\ branch: f1
149 149 | | tag: tip
150 150 | | parent: 7:4c9fbe56a16f
151 151 | | parent: 9:e31216eec445
152 152 | | user: szhang
153 153 | | date: Thu Sep 05 12:59:39 2013 -0400
154 154 | | summary: merge
155 155 | |
156 156 | o changeset: 9:e31216eec445
157 157 | | branch: f1
158 158 | | user: szhang
159 159 | | date: Thu Sep 05 12:59:10 2013 -0400
160 160 | | summary: more changes to f1
161 161 | |
162 162 | o changeset: 8:8e4e2c1a07ae
163 163 | |\ branch: f1
164 164 | | | parent: 2:4bc80088dc6b
165 165 | | | parent: 6:400110238667
166 166 | | | user: szhang
167 167 | | | date: Thu Sep 05 12:57:59 2013 -0400
168 168 | | | summary: bad merge
169 169 | | |
170 170 o | | changeset: 7:4c9fbe56a16f
171 171 |/ / branch: f1
172 172 | | parent: 2:4bc80088dc6b
173 173 | | user: szhang
174 174 | | date: Thu Sep 05 12:54:00 2013 -0400
175 175 | | summary: changed f1
176 176 | |
177 177 | o changeset: 6:400110238667
178 178 | | branch: f2
179 179 | | parent: 4:12e8ec6bb010
180 180 | | user: szhang
181 181 | | date: Tue Sep 03 13:58:02 2013 -0400
182 182 | | summary: changed f2 on f2
183 183 | |
184 184 | | @ changeset: 5:d79e2059b5c0
185 185 | | | parent: 3:8a951942e016
186 186 | | | user: szhang
187 187 | | | date: Tue Sep 03 13:57:39 2013 -0400
188 188 | | | summary: changed f2 on default
189 189 | | |
190 190 | o | changeset: 4:12e8ec6bb010
191 191 | |/ branch: f2
192 192 | | user: szhang
193 193 | | date: Tue Sep 03 13:57:18 2013 -0400
194 194 | | summary: created f2 branch
195 195 | |
196 196 | o changeset: 3:8a951942e016
197 197 | | parent: 0:24797d4f68de
198 198 | | user: szhang
199 199 | | date: Tue Sep 03 13:57:11 2013 -0400
200 200 | | summary: added f2.txt
201 201 | |
202 202 o | changeset: 2:4bc80088dc6b
203 203 | | branch: f1
204 204 | | user: szhang
205 205 | | date: Tue Sep 03 13:56:20 2013 -0400
206 206 | | summary: added f1.txt
207 207 | |
208 208 o | changeset: 1:ef53c9e6b608
209 209 |/ branch: f1
210 210 | user: szhang
211 211 | date: Tue Sep 03 13:55:26 2013 -0400
212 212 | summary: created f1 branch
213 213 |
214 214 o changeset: 0:24797d4f68de
215 215 user: szhang
216 216 date: Tue Sep 03 13:55:08 2013 -0400
217 217 summary: added default.txt
218 218
219 219 $ hg rebase -s9 -d2 --debug # use debug to really check merge base used
220 220 rebase onto 2 starting from e31216eec445
221 221 ignoring null merge rebase of 3
222 222 ignoring null merge rebase of 4
223 223 ignoring null merge rebase of 6
224 224 ignoring null merge rebase of 8
225 225 rebasing 9:e31216eec445 "more changes to f1"
226 226 rebasing: 9:e31216eec445 5/6 changesets (83.33%)
227 227 future parents are 2 and -1
228 228 rebase status stored
229 229 update to 2:4bc80088dc6b
230 230 resolving manifests
231 231 branchmerge: False, force: True, partial: False
232 232 ancestor: d79e2059b5c0+, local: d79e2059b5c0+, remote: 4bc80088dc6b
233 233 f2.txt: other deleted -> r
234 234 removing f2.txt
235 235 updating: f2.txt 1/2 files (50.00%)
236 236 f1.txt: remote created -> g
237 237 getting f1.txt
238 238 updating: f1.txt 2/2 files (100.00%)
239 239 merge against 9:e31216eec445
240 240 detach base 8:8e4e2c1a07ae
241 241 searching for copies back to rev 3
242 242 resolving manifests
243 243 branchmerge: True, force: True, partial: False
244 244 ancestor: 8e4e2c1a07ae, local: 4bc80088dc6b+, remote: e31216eec445
245 245 f1.txt: remote is newer -> g
246 246 getting f1.txt
247 247 updating: f1.txt 1/1 files (100.00%)
248 248 committing files:
249 249 f1.txt
250 250 committing manifest
251 251 committing changelog
252 252 rebased as 19c888675e13
253 253 rebasing 10:2f2496ddf49d "merge" (tip)
254 254 rebasing: 10:2f2496ddf49d 6/6 changesets (100.00%)
255 255 future parents are 11 and 7
256 256 rebase status stored
257 257 already in target
258 258 merge against 10:2f2496ddf49d
259 259 detach base 9:e31216eec445
260 260 searching for copies back to rev 3
261 261 resolving manifests
262 262 branchmerge: True, force: True, partial: False
263 263 ancestor: e31216eec445, local: 19c888675e13+, remote: 2f2496ddf49d
264 264 f1.txt: remote is newer -> g
265 265 getting f1.txt
266 266 updating: f1.txt 1/1 files (100.00%)
267 267 committing files:
268 268 f1.txt
269 269 committing manifest
270 270 committing changelog
271 271 rebased as 2a7f09cac94c
272 272 rebase merging completed
273 273 update back to initial working directory parent
274 274 resolving manifests
275 275 branchmerge: False, force: False, partial: False
276 276 ancestor: 2a7f09cac94c, local: 2a7f09cac94c+, remote: d79e2059b5c0
277 277 f1.txt: other deleted -> r
278 278 removing f1.txt
279 279 updating: f1.txt 1/2 files (50.00%)
280 280 f2.txt: remote created -> g
281 281 getting f2.txt
282 282 updating: f2.txt 2/2 files (100.00%)
283 283 3 changesets found
284 284 list of changesets:
285 285 4c9fbe56a16f30c0d5dcc40ec1a97bbe3325209c
286 286 e31216eec445e44352c5f01588856059466a24c9
287 287 2f2496ddf49d69b5ef23ad8cf9fb2e0e4faf0ac2
288 288 bundling: 1/3 changesets (33.33%)
289 289 bundling: 2/3 changesets (66.67%)
290 290 bundling: 3/3 changesets (100.00%)
291 291 bundling: 1/3 manifests (33.33%)
292 292 bundling: 2/3 manifests (66.67%)
293 293 bundling: 3/3 manifests (100.00%)
294 294 bundling: f1.txt 1/1 files (100.00%)
295 295 saved backup bundle to $TESTTMP/issue4041/.hg/strip-backup/e31216eec445-15f7a814-backup.hg (glob)
296 296 3 changesets found
297 297 list of changesets:
298 298 4c9fbe56a16f30c0d5dcc40ec1a97bbe3325209c
299 299 19c888675e133ab5dff84516926a65672eaf04d9
300 300 2a7f09cac94c7f4b73ebd5cd1a62d3b2e8e336bf
301 301 bundling: 1/3 changesets (33.33%)
302 302 bundling: 2/3 changesets (66.67%)
303 303 bundling: 3/3 changesets (100.00%)
304 304 bundling: 1/3 manifests (33.33%)
305 305 bundling: 2/3 manifests (66.67%)
306 306 bundling: 3/3 manifests (100.00%)
307 307 bundling: f1.txt 1/1 files (100.00%)
308 308 adding branch
309 309 adding changesets
310 310 changesets: 1 chunks
311 311 add changeset 4c9fbe56a16f
312 312 changesets: 2 chunks
313 313 add changeset 19c888675e13
314 314 changesets: 3 chunks
315 315 add changeset 2a7f09cac94c
316 316 adding manifests
317 317 manifests: 1/2 chunks (50.00%)
318 318 manifests: 2/2 chunks (100.00%)
319 319 manifests: 3/2 chunks (150.00%)
320 320 adding file changes
321 321 adding f1.txt revisions
322 322 files: 1/1 chunks (100.00%)
323 323 added 2 changesets with 2 changes to 1 files
324 324 invalid branchheads cache (served): tip differs
325 truncating cache/rbc-revs-v1 to 72
325 326 rebase completed
326 327 updating the branch cache
General Comments 0
You need to be logged in to leave comments. Login now