##// END OF EJS Templates
rev-branch-cache: stop pretending we will overwrite data when we don't...
marmoute -
r52867:4c885d5f default
parent child Browse files
Show More
@@ -1,427 +1,434
1 1 # rev_cache.py - caching branch information per revision
2 2 #
3 3 # This software may be used and distributed according to the terms of the
4 4 # GNU General Public License version 2 or any later version.
5 5 from __future__ import annotations
6 6
7 7 import os
8 8 import struct
9 9
10 10 from ..node import (
11 11 nullrev,
12 12 )
13 13
14 14 from .. import (
15 15 encoding,
16 16 error,
17 17 util,
18 18 )
19 19
20 20 from ..utils import (
21 21 stringutil,
22 22 )
23 23
24 24 calcsize = struct.calcsize
25 25 pack_into = struct.pack_into
26 26 unpack_from = struct.unpack_from
27 27
28 28
29 29 # Revision branch info cache
30 30
31 31 # The "V2" version use the same format as the "V1" but garantee it won't be
32 32 # truncated, preventing SIGBUS when it is mmap-ed
33 33 _rbcversion = b'-v2'
34 34 _rbcnames = b'rbc-names' + _rbcversion
35 35 _rbcrevs = b'rbc-revs' + _rbcversion
36 36 _rbc_legacy_version = b'-v1'
37 37 _rbc_legacy_names = b'rbc-names' + _rbc_legacy_version
38 38 _rbc_legacy_revs = b'rbc-revs' + _rbc_legacy_version
39 39 # [4 byte hash prefix][4 byte branch name number with sign bit indicating open]
40 40 _rbcrecfmt = b'>4sI'
41 41 _rbcrecsize = calcsize(_rbcrecfmt)
42 42 _rbcmininc = 64 * _rbcrecsize
43 43 _rbcnodelen = 4
44 44 _rbcbranchidxmask = 0x7FFFFFFF
45 45 _rbccloseflag = 0x80000000
46 46
47 47
48 48 # with atomic replacement.
49 49 REWRITE_RATIO = 0.2
50 50
51 51
52 52 class rbcrevs:
53 53 """a byte string consisting of an immutable prefix followed by a mutable suffix"""
54 54
55 55 def __init__(self, revs):
56 56 self._prefix = revs
57 57 self._rest = bytearray()
58 58
59 59 def __len__(self):
60 60 return len(self._prefix) + len(self._rest)
61 61
62 62 def unpack_record(self, rbcrevidx):
63 63 if rbcrevidx < len(self._prefix):
64 64 return unpack_from(_rbcrecfmt, util.buffer(self._prefix), rbcrevidx)
65 65 else:
66 66 return unpack_from(
67 67 _rbcrecfmt,
68 68 util.buffer(self._rest),
69 69 rbcrevidx - len(self._prefix),
70 70 )
71 71
72 72 def make_mutable(self):
73 73 if len(self._prefix) > 0:
74 74 entirety = bytearray()
75 75 entirety[:] = self._prefix
76 76 entirety.extend(self._rest)
77 77 self._rest = entirety
78 78 self._prefix = bytearray()
79 79
80 80 def truncate(self, pos):
81 81 self.make_mutable()
82 82 del self._rest[pos:]
83 83
84 84 def pack_into(self, rbcrevidx, node, branchidx):
85 85 if rbcrevidx < len(self._prefix):
86 86 self.make_mutable()
87 87 buf = self._rest
88 88 start_offset = rbcrevidx - len(self._prefix)
89 89 end_offset = start_offset + _rbcrecsize
90 90
91 91 if len(self._rest) < end_offset:
92 92 # bytearray doesn't allocate extra space at least in Python 3.7.
93 93 # When multiple changesets are added in a row, precise resize would
94 94 # result in quadratic complexity. Overallocate to compensate by
95 95 # using the classic doubling technique for dynamic arrays instead.
96 96 # If there was a gap in the map before, less space will be reserved.
97 97 self._rest.extend(b'\0' * end_offset)
98 98 return pack_into(
99 99 _rbcrecfmt,
100 100 buf,
101 101 start_offset,
102 102 node,
103 103 branchidx,
104 104 )
105 105
106 106 def extend(self, extension):
107 107 return self._rest.extend(extension)
108 108
109 109 def slice(self, begin, end):
110 110 if begin < len(self._prefix):
111 111 acc = bytearray()
112 112 acc[:] = self._prefix[begin:end]
113 113 acc.extend(
114 114 self._rest[begin - len(self._prefix) : end - len(self._prefix)]
115 115 )
116 116 return acc
117 117 return self._rest[begin - len(self._prefix) : end - len(self._prefix)]
118 118
119 119
120 120 class revbranchcache:
121 121 """Persistent cache, mapping from revision number to branch name and close.
122 122 This is a low level cache, independent of filtering.
123 123
124 124 Branch names are stored in rbc-names in internal encoding separated by 0.
125 125 rbc-names is append-only, and each branch name is only stored once and will
126 126 thus have a unique index.
127 127
128 128 The branch info for each revision is stored in rbc-revs as constant size
129 129 records. The whole file is read into memory, but it is only 'parsed' on
130 130 demand. The file is usually append-only but will be truncated if repo
131 131 modification is detected.
132 132 The record for each revision contains the first 4 bytes of the
133 133 corresponding node hash, and the record is only used if it still matches.
134 134 Even a completely trashed rbc-revs fill thus still give the right result
135 135 while converging towards full recovery ... assuming no incorrectly matching
136 136 node hashes.
137 137 The record also contains 4 bytes where 31 bits contains the index of the
138 138 branch and the last bit indicate that it is a branch close commit.
139 139 The usage pattern for rbc-revs is thus somewhat similar to 00changelog.i
140 140 and will grow with it but be 1/8th of its size.
141 141 """
142 142
143 143 def __init__(self, repo, readonly=True):
144 144 assert repo.filtername is None
145 145 self._repo = repo
146 146 self._names = [] # branch names in local encoding with static index
147 147 self._rbcrevs = rbcrevs(bytearray())
148 148 self._rbcsnameslen = 0 # length of names read at _rbcsnameslen
149 149 self._force_overwrite = False
150 150 v1_fallback = False
151 151 try:
152 152 try:
153 153 bndata = repo.cachevfs.read(_rbcnames)
154 154 except (IOError, OSError):
155 155 # If we don't have "v2" data, we might have "v1" data worth
156 156 # using.
157 157 #
158 158 # consider stop doing this many version after hg-6.9 release
159 159 bndata = repo.cachevfs.read(_rbc_legacy_names)
160 160 v1_fallback = True
161 161 self._force_overwrite = True
162 162 self._rbcsnameslen = len(bndata) # for verification before writing
163 163 if bndata:
164 164 self._names = [
165 165 encoding.tolocal(bn) for bn in bndata.split(b'\0')
166 166 ]
167 167 except (IOError, OSError):
168 168 if readonly:
169 169 # don't try to use cache - fall back to the slow path
170 170 self.branchinfo = self._branchinfo
171 171
172 172 if self._names:
173 173 try:
174 174 usemmap = repo.ui.configbool(b'storage', b'revbranchcache.mmap')
175 175 if not v1_fallback:
176 176 with repo.cachevfs(_rbcrevs) as fp:
177 177 if usemmap and repo.cachevfs.is_mmap_safe(_rbcrevs):
178 178 data = util.buffer(util.mmapread(fp))
179 179 else:
180 180 data = fp.read()
181 181 else:
182 182 # If we don't have "v2" data, we might have "v1" data worth
183 183 # using.
184 184 #
185 185 # Consider stop doing this many version after hg-6.9
186 186 # release.
187 187 with repo.cachevfs(_rbc_legacy_revs) as fp:
188 188 data = fp.read()
189 189 self._rbcrevs = rbcrevs(data)
190 190 except (IOError, OSError) as inst:
191 191 repo.ui.debug(
192 192 b"couldn't read revision branch cache: %s\n"
193 193 % stringutil.forcebytestr(inst)
194 194 )
195 195 # remember number of good records on disk
196 196 self._rbcrevslen = min(
197 197 len(self._rbcrevs) // _rbcrecsize, len(repo.changelog)
198 198 )
199 199 if self._rbcrevslen == 0:
200 200 self._names = []
201 201 self._rbcnamescount = len(self._names) # number of names read at
202 202 # _rbcsnameslen
203 203
204 204 def _clear(self):
205 205 self._rbcsnameslen = 0
206 206 del self._names[:]
207 207 self._rbcnamescount = 0
208 208 self._rbcrevslen = len(self._repo.changelog)
209 209 self._rbcrevs = rbcrevs(bytearray(self._rbcrevslen * _rbcrecsize))
210 210 util.clearcachedproperty(self, b'_namesreverse')
211 211 self._force_overwrite = True
212 212
213 213 def invalidate(self, rev=0):
214 214 self._rbcrevslen = rev
215 215 self._rbcrevs.truncate(rev)
216 216 self._force_overwrite = True
217 217
218 218 @util.propertycache
219 219 def _namesreverse(self):
220 220 return {b: r for r, b in enumerate(self._names)}
221 221
222 222 def branchinfo(self, rev):
223 223 """Return branch name and close flag for rev, using and updating
224 224 persistent cache."""
225 225 changelog = self._repo.changelog
226 226 rbcrevidx = rev * _rbcrecsize
227 227
228 228 # avoid negative index, changelog.read(nullrev) is fast without cache
229 229 if rev == nullrev:
230 230 return changelog.branchinfo(rev)
231 231
232 232 # if requested rev isn't allocated, grow and cache the rev info
233 233 if len(self._rbcrevs) < rbcrevidx + _rbcrecsize:
234 234 return self._branchinfo(rev)
235 235
236 236 # fast path: extract data from cache, use it if node is matching
237 237 reponode = changelog.node(rev)[:_rbcnodelen]
238 238 cachenode, branchidx = self._rbcrevs.unpack_record(rbcrevidx)
239 239 close = bool(branchidx & _rbccloseflag)
240 240 if close:
241 241 branchidx &= _rbcbranchidxmask
242 242 if cachenode == b'\0\0\0\0':
243 243 pass
244 244 elif cachenode == reponode:
245 245 try:
246 246 return self._names[branchidx], close
247 247 except IndexError:
248 248 # recover from invalid reference to unknown branch
249 249 self._repo.ui.debug(
250 250 b"referenced branch names not found"
251 251 b" - rebuilding revision branch cache from scratch\n"
252 252 )
253 253 self._clear()
254 254 else:
255 255 # rev/node map has changed, invalidate the cache from here up
256 256 self._repo.ui.debug(
257 257 b"history modification detected - truncating "
258 258 b"revision branch cache to revision %d\n" % rev
259 259 )
260 260 truncate = rbcrevidx + _rbcrecsize
261 261 self._rbcrevs.truncate(truncate)
262 262 self._rbcrevslen = min(self._rbcrevslen, truncate)
263 263
264 264 # fall back to slow path and make sure it will be written to disk
265 265 return self._branchinfo(rev)
266 266
267 267 def _branchinfo(self, rev):
268 268 """Retrieve branch info from changelog and update _rbcrevs"""
269 269 changelog = self._repo.changelog
270 270 b, close = changelog.branchinfo(rev)
271 271 if b in self._namesreverse:
272 272 branchidx = self._namesreverse[b]
273 273 else:
274 274 branchidx = len(self._names)
275 275 self._names.append(b)
276 276 self._namesreverse[b] = branchidx
277 277 reponode = changelog.node(rev)
278 278 if close:
279 279 branchidx |= _rbccloseflag
280 280 self._setcachedata(rev, reponode, branchidx)
281 281 return b, close
282 282
283 283 def setdata(self, rev, changelogrevision):
284 284 """add new data information to the cache"""
285 285 branch, close = changelogrevision.branchinfo
286 286
287 287 if branch in self._namesreverse:
288 288 branchidx = self._namesreverse[branch]
289 289 else:
290 290 branchidx = len(self._names)
291 291 self._names.append(branch)
292 292 self._namesreverse[branch] = branchidx
293 293 if close:
294 294 branchidx |= _rbccloseflag
295 295 self._setcachedata(rev, self._repo.changelog.node(rev), branchidx)
296 296 # If no cache data were readable (non exists, bad permission, etc)
297 297 # the cache was bypassing itself by setting:
298 298 #
299 299 # self.branchinfo = self._branchinfo
300 300 #
301 301 # Since we now have data in the cache, we need to drop this bypassing.
302 302 if 'branchinfo' in vars(self):
303 303 del self.branchinfo
304 304
305 305 def _setcachedata(self, rev, node, branchidx):
306 306 """Writes the node's branch data to the in-memory cache data."""
307 307 if rev == nullrev:
308 308 return
309 309 rbcrevidx = rev * _rbcrecsize
310 310 self._rbcrevs.pack_into(rbcrevidx, node, branchidx)
311 311 self._rbcrevslen = min(self._rbcrevslen, rev)
312 312
313 313 tr = self._repo.currenttransaction()
314 314 if tr:
315 315 tr.addfinalize(b'write-revbranchcache', self.write)
316 316
317 317 def write(self, tr=None):
318 318 """Save branch cache if it is dirty."""
319 319 repo = self._repo
320 320 wlock = None
321 321 step = b''
322 322 try:
323 323 # write the new names
324 324 if self._force_overwrite or self._rbcnamescount < len(self._names):
325 325 wlock = repo.wlock(wait=False)
326 326 step = b' names'
327 327 self._writenames(repo)
328 328
329 329 # write the new revs
330 330 start = self._rbcrevslen * _rbcrecsize
331 331 if self._force_overwrite or start != len(self._rbcrevs):
332 332 step = b''
333 333 if wlock is None:
334 334 wlock = repo.wlock(wait=False)
335 335 self._writerevs(repo, start)
336 336
337 337 except (IOError, OSError, error.Abort, error.LockError) as inst:
338 338 repo.ui.debug(
339 339 b"couldn't write revision branch cache%s: %s\n"
340 340 % (step, stringutil.forcebytestr(inst))
341 341 )
342 342 finally:
343 343 if wlock is not None:
344 344 wlock.release()
345 345
346 346 def _writenames(self, repo):
347 347 """write the new branch names to revbranchcache"""
348 348 f = None
349 349 if self._force_overwrite:
350 350 self._rbcsnameslen = 0
351 351 self._rbcnamescount = 0
352 352 try:
353 353 if self._force_overwrite or self._rbcnamescount != 0:
354 354 f = repo.cachevfs.open(_rbcnames, b'ab')
355 355 current_size = f.tell()
356 356 if current_size == self._rbcsnameslen:
357 357 f.write(b'\0')
358 358 else:
359 359 f.close()
360 360 if self._force_overwrite:
361 361 dbg = b"resetting content of %s\n"
362 362 elif current_size > 0:
363 363 dbg = b"%s changed - rewriting it\n"
364 364 else:
365 365 dbg = b"%s is missing - rewriting it\n"
366 366 repo.ui.debug(dbg % _rbcnames)
367 367 self._rbcnamescount = 0
368 368 self._rbcrevslen = 0
369 369 if self._rbcnamescount == 0:
370 370 # before rewriting names, make sure references are removed
371 371 repo.cachevfs.unlinkpath(_rbcrevs, ignoremissing=True)
372 372 f = repo.cachevfs.open(_rbcnames, b'wb')
373 373 names = self._names[self._rbcnamescount :]
374 374 from_local = encoding.fromlocal
375 375 data = b'\0'.join(from_local(b) for b in names)
376 376 f.write(data)
377 377 self._rbcsnameslen = f.tell()
378 378 finally:
379 379 if f is not None:
380 380 f.close()
381 381 self._rbcnamescount = len(self._names)
382 382
383 383 def _writerevs(self, repo, start):
384 384 """write the new revs to revbranchcache"""
385 385 revs = min(len(repo.changelog), len(self._rbcrevs) // _rbcrecsize)
386 386
387 387 end = revs * _rbcrecsize
388 388 if self._force_overwrite:
389 389 start = 0
390 390
391 391 with repo.cachevfs.open(_rbcrevs, b'a+b') as f:
392 392 pass # this make sure the file exist…
393 393 with repo.cachevfs.open(_rbcrevs, b'r+b') as f:
394 394 f.seek(0, os.SEEK_END)
395 395 current_size = f.tell()
396 396 if current_size < start:
397 397 start = 0
398 398 if current_size != start:
399 399 threshold = current_size * REWRITE_RATIO
400 if (max(end, current_size) - start) < threshold:
401 # end affected, let overwrite the bad value
402 400 overwritten = min(end, current_size) - start
401 if (max(end, current_size) - start) >= threshold:
402 start = 0
403 dbg = b"resetting content of cache/%s\n" % _rbcrevs
404 repo.ui.debug(dbg)
405 elif overwritten > 0:
406 # end affected, let us overwrite the bad value
403 407 dbg = b"overwriting %d bytes from %d in cache/%s"
404 dbg %= (overwritten, start, _rbcrevs)
408 dbg %= (current_size - start, start, _rbcrevs)
405 409 if end < current_size:
406 410 extra = b" leaving (%d trailing bytes)"
407 411 extra %= current_size - end
408 412 dbg += extra
409 413 dbg += b'\n'
410 414 repo.ui.debug(dbg)
411 415 else:
412 start = 0
413 dbg = b"resetting content of cache/%s\n" % _rbcrevs
416 # extra untouched data at the end, lets warn about them
417 assert start == end # since don't write anything
418 dbg = b"cache/%s contains %d unknown trailing bytes\n"
419 dbg %= (_rbcrevs, current_size - start)
414 420 repo.ui.debug(dbg)
421
415 422 if start > 0:
416 423 f.seek(start)
417 424 f.write(self._rbcrevs.slice(start, end))
418 425 else:
419 426 f.close()
420 427 with repo.cachevfs.open(
421 428 _rbcrevs,
422 429 b'wb',
423 430 atomictemp=True,
424 431 ) as rev_file:
425 432 rev_file.write(self._rbcrevs.slice(start, end))
426 433 self._rbcrevslen = revs
427 434 self._force_overwrite = False
@@ -1,1466 +1,1466
1 1 #testcases mmap nommap
2 2 #testcases v2 v3
3 3
4 4 #if mmap
5 5 $ cat <<EOF >> $HGRCPATH
6 6 > [storage]
7 7 > revbranchcache.mmap=true
8 8 > EOF
9 9 #endif
10 10
11 11 #if v3
12 12 $ cat <<EOF >> $HGRCPATH
13 13 > [experimental]
14 14 > branch-cache-v3=yes
15 15 > EOF
16 16 #else
17 17 $ cat <<EOF >> $HGRCPATH
18 18 > [experimental]
19 19 > branch-cache-v3=no
20 20 > EOF
21 21 #endif
22 22
23 23 $ hg init a
24 24 $ cd a
25 25
26 26 Verify checking branch of nullrev before the cache is created doesnt crash
27 27 $ hg log -r 'branch(.)' -T '{branch}\n'
28 28
29 29 Basic test
30 30 $ echo 'root' >root
31 31 $ hg add root
32 32 $ hg commit -d '0 0' -m "Adding root node"
33 33
34 34 $ echo 'a' >a
35 35 $ hg add a
36 36 $ hg branch a
37 37 marked working directory as branch a
38 38 (branches are permanent and global, did you want a bookmark?)
39 39 $ hg commit -d '1 0' -m "Adding a branch"
40 40
41 41 $ hg branch q
42 42 marked working directory as branch q
43 43 $ echo 'aa' >a
44 44 $ hg branch -C
45 45 reset working directory to branch a
46 46 $ hg commit -d '2 0' -m "Adding to a branch"
47 47
48 48 $ hg update -C 0
49 49 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
50 50 $ echo 'b' >b
51 51 $ hg add b
52 52 $ hg branch b
53 53 marked working directory as branch b
54 54 $ hg commit -d '2 0' -m "Adding b branch"
55 55
56 56 $ echo 'bh1' >bh1
57 57 $ hg add bh1
58 58 $ hg commit -d '3 0' -m "Adding b branch head 1"
59 59
60 60 $ hg update -C 2
61 61 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
62 62 $ echo 'bh2' >bh2
63 63 $ hg add bh2
64 64 $ hg commit -d '4 0' -m "Adding b branch head 2"
65 65
66 66 $ echo 'c' >c
67 67 $ hg add c
68 68 $ hg branch c
69 69 marked working directory as branch c
70 70 $ hg commit -d '5 0' -m "Adding c branch"
71 71
72 72 reserved names
73 73
74 74 $ hg branch tip
75 75 abort: the name 'tip' is reserved
76 76 [10]
77 77 $ hg branch null
78 78 abort: the name 'null' is reserved
79 79 [10]
80 80 $ hg branch .
81 81 abort: the name '.' is reserved
82 82 [10]
83 83
84 84 invalid characters
85 85
86 86 $ hg branch 'foo:bar'
87 87 abort: ':' cannot be used in a name
88 88 [10]
89 89
90 90 $ hg branch 'foo
91 91 > bar'
92 92 abort: '\n' cannot be used in a name
93 93 [10]
94 94
95 95 trailing or leading spaces should be stripped before testing duplicates
96 96
97 97 $ hg branch 'b '
98 98 abort: a branch of the same name already exists
99 99 (use 'hg update' to switch to it)
100 100 [10]
101 101
102 102 $ hg branch ' b'
103 103 abort: a branch of the same name already exists
104 104 (use 'hg update' to switch to it)
105 105 [10]
106 106
107 107 underscores in numeric branch names (issue6737)
108 108
109 109 $ hg branch 2700_210
110 110 marked working directory as branch 2700_210
111 111
112 112 verify update will accept invalid legacy branch names
113 113
114 114 $ hg init test-invalid-branch-name
115 115 $ cd test-invalid-branch-name
116 116 $ hg unbundle -u "$TESTDIR"/bundles/test-invalid-branch-name.hg
117 117 adding changesets
118 118 adding manifests
119 119 adding file changes
120 120 added 3 changesets with 3 changes to 2 files
121 121 new changesets f0e4c7f04036:33c2ceb9310b (3 drafts)
122 122 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
123 123
124 124 $ hg update '"colon:test"'
125 125 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 126 $ cd ..
127 127
128 128 $ echo 'd' >d
129 129 $ hg add d
130 130 $ hg branch 'a branch name much longer than the default justification used by branches'
131 131 marked working directory as branch a branch name much longer than the default justification used by branches
132 132 $ hg commit -d '6 0' -m "Adding d branch"
133 133
134 134 $ hg branches
135 135 a branch name much longer than the default justification used by branches 7:10ff5895aa57
136 136 b 4:aee39cd168d0
137 137 c 6:589736a22561 (inactive)
138 138 a 5:d8cbc61dbaa6 (inactive)
139 139 default 0:19709c5a4e75 (inactive)
140 140
141 141 -------
142 142
143 143 $ hg branches -a
144 144 a branch name much longer than the default justification used by branches 7:10ff5895aa57
145 145 b 4:aee39cd168d0
146 146
147 147 --- Branch a
148 148
149 149 $ hg log -b a
150 150 changeset: 5:d8cbc61dbaa6
151 151 branch: a
152 152 parent: 2:881fe2b92ad0
153 153 user: test
154 154 date: Thu Jan 01 00:00:04 1970 +0000
155 155 summary: Adding b branch head 2
156 156
157 157 changeset: 2:881fe2b92ad0
158 158 branch: a
159 159 user: test
160 160 date: Thu Jan 01 00:00:02 1970 +0000
161 161 summary: Adding to a branch
162 162
163 163 changeset: 1:dd6b440dd85a
164 164 branch: a
165 165 user: test
166 166 date: Thu Jan 01 00:00:01 1970 +0000
167 167 summary: Adding a branch
168 168
169 169
170 170 ---- Branch b
171 171
172 172 $ hg log -b b
173 173 changeset: 4:aee39cd168d0
174 174 branch: b
175 175 user: test
176 176 date: Thu Jan 01 00:00:03 1970 +0000
177 177 summary: Adding b branch head 1
178 178
179 179 changeset: 3:ac22033332d1
180 180 branch: b
181 181 parent: 0:19709c5a4e75
182 182 user: test
183 183 date: Thu Jan 01 00:00:02 1970 +0000
184 184 summary: Adding b branch
185 185
186 186
187 187 ---- going to test branch listing by rev
188 188 $ hg branches -r0
189 189 default 0:19709c5a4e75 (inactive)
190 190 $ hg branches -qr0
191 191 default
192 192 --- now more than one rev
193 193 $ hg branches -r2:5
194 194 b 4:aee39cd168d0
195 195 a 5:d8cbc61dbaa6 (inactive)
196 196 $ hg branches -qr2:5
197 197 b
198 198 a
199 199 ---- going to test branch closing
200 200
201 201 $ hg branches
202 202 a branch name much longer than the default justification used by branches 7:10ff5895aa57
203 203 b 4:aee39cd168d0
204 204 c 6:589736a22561 (inactive)
205 205 a 5:d8cbc61dbaa6 (inactive)
206 206 default 0:19709c5a4e75 (inactive)
207 207 $ hg up -C b
208 208 2 files updated, 0 files merged, 4 files removed, 0 files unresolved
209 209 $ echo 'xxx1' >> b
210 210 $ hg commit -d '7 0' -m 'adding cset to branch b'
211 211 $ hg up -C aee39cd168d0
212 212 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
213 213 $ echo 'xxx2' >> b
214 214 $ hg commit -d '8 0' -m 'adding head to branch b'
215 215 created new head
216 216 $ echo 'xxx3' >> b
217 217 $ hg commit -d '9 0' -m 'adding another cset to branch b'
218 218 $ hg branches
219 219 b 10:bfbe841b666e
220 220 a branch name much longer than the default justification used by branches 7:10ff5895aa57
221 221 c 6:589736a22561 (inactive)
222 222 a 5:d8cbc61dbaa6 (inactive)
223 223 default 0:19709c5a4e75 (inactive)
224 224 $ hg heads --closed
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 heads
264 264 changeset: 10:bfbe841b666e
265 265 branch: b
266 266 tag: tip
267 267 user: test
268 268 date: Thu Jan 01 00:00:09 1970 +0000
269 269 summary: adding another cset to branch b
270 270
271 271 changeset: 8:eebb944467c9
272 272 branch: b
273 273 parent: 4:aee39cd168d0
274 274 user: test
275 275 date: Thu Jan 01 00:00:07 1970 +0000
276 276 summary: adding cset to branch b
277 277
278 278 changeset: 7:10ff5895aa57
279 279 branch: a branch name much longer than the default justification used by branches
280 280 user: test
281 281 date: Thu Jan 01 00:00:06 1970 +0000
282 282 summary: Adding d branch
283 283
284 284 changeset: 6:589736a22561
285 285 branch: c
286 286 user: test
287 287 date: Thu Jan 01 00:00:05 1970 +0000
288 288 summary: Adding c branch
289 289
290 290 changeset: 5:d8cbc61dbaa6
291 291 branch: a
292 292 parent: 2:881fe2b92ad0
293 293 user: test
294 294 date: Thu Jan 01 00:00:04 1970 +0000
295 295 summary: Adding b branch head 2
296 296
297 297 changeset: 0:19709c5a4e75
298 298 user: test
299 299 date: Thu Jan 01 00:00:00 1970 +0000
300 300 summary: Adding root node
301 301
302 302 $ hg commit -d '9 0' --close-branch -m 'prune bad branch'
303 303 $ hg branches -a
304 304 b 8:eebb944467c9
305 305 a branch name much longer than the default justification used by branches 7:10ff5895aa57
306 306 $ hg up -C b
307 307 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
308 308 $ hg commit -d '9 0' --close-branch -m 'close this part branch too'
309 309 $ hg commit -d '9 0' --close-branch -m 're-closing this branch'
310 310 abort: current revision is already a branch closing head
311 311 [10]
312 312
313 313 $ echo foo > b
314 314 $ hg commit -d '9 0' --close-branch -m 're-closing this branch'
315 315
316 316 $ echo bar > b
317 317 $ hg commit -d '9 0' --close-branch -m 're-closing this branch' bh1
318 318 abort: current revision is already a branch closing head
319 319 [10]
320 320 $ hg commit -d '9 0' --close-branch -m 're-closing this branch' b
321 321
322 322 $ echo baz > b
323 323 $ hg commit -d '9 0' --close-branch -m 'empty re-closing this branch' -X b
324 324 abort: current revision is already a branch closing head
325 325 [10]
326 326 $ hg revert b
327 327
328 328 $ hg debugstrip --rev 13: --no-backup
329 329 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
330 330 $ hg revert --all --no-backup
331 331
332 332 $ hg log -r tip --debug
333 333 changeset: 12:e3d49c0575d8fc2cb1cd6859c747c14f5f6d499f
334 334 branch: b
335 335 tag: tip
336 336 phase: draft
337 337 parent: 8:eebb944467c9fb9651ed232aeaf31b3c0a7fc6c1
338 338 parent: -1:0000000000000000000000000000000000000000
339 339 manifest: 8:6f9ed32d2b310e391a4f107d5f0f071df785bfee
340 340 user: test
341 341 date: Thu Jan 01 00:00:09 1970 +0000
342 342 extra: branch=b
343 343 extra: close=1
344 344 description:
345 345 close this part branch too
346 346
347 347
348 348 --- b branch should be inactive
349 349
350 350 $ hg branches
351 351 a branch name much longer than the default justification used by branches 7:10ff5895aa57
352 352 c 6:589736a22561 (inactive)
353 353 a 5:d8cbc61dbaa6 (inactive)
354 354 default 0:19709c5a4e75 (inactive)
355 355 $ hg branches -c
356 356 a branch name much longer than the default justification used by branches 7:10ff5895aa57
357 357 b 12:e3d49c0575d8 (closed)
358 358 c 6:589736a22561 (inactive)
359 359 a 5:d8cbc61dbaa6 (inactive)
360 360 default 0:19709c5a4e75 (inactive)
361 361 $ hg branches -a
362 362 a branch name much longer than the default justification used by branches 7:10ff5895aa57
363 363 $ hg branches -q
364 364 a branch name much longer than the default justification used by branches
365 365 c
366 366 a
367 367 default
368 368 $ hg heads b
369 369 no open branch heads found on branches b
370 370 [1]
371 371 $ hg heads --closed b
372 372 changeset: 12:e3d49c0575d8
373 373 branch: b
374 374 tag: tip
375 375 parent: 8:eebb944467c9
376 376 user: test
377 377 date: Thu Jan 01 00:00:09 1970 +0000
378 378 summary: close this part branch too
379 379
380 380 changeset: 11:d3f163457ebf
381 381 branch: b
382 382 user: test
383 383 date: Thu Jan 01 00:00:09 1970 +0000
384 384 summary: prune bad branch
385 385
386 386 $ echo 'xxx4' >> b
387 387 $ hg commit -d '9 0' -m 'reopen branch with a change'
388 388 reopening closed branch head 12
389 389
390 390 --- branch b is back in action
391 391
392 392 $ hg branches -a
393 393 b 13:e23b5505d1ad
394 394 a branch name much longer than the default justification used by branches 7:10ff5895aa57
395 395
396 396 ---- test heads listings
397 397
398 398 $ hg heads
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 changeset: 7:10ff5895aa57
407 407 branch: a branch name much longer than the default justification used by branches
408 408 user: test
409 409 date: Thu Jan 01 00:00:06 1970 +0000
410 410 summary: Adding d branch
411 411
412 412 changeset: 6:589736a22561
413 413 branch: c
414 414 user: test
415 415 date: Thu Jan 01 00:00:05 1970 +0000
416 416 summary: Adding c branch
417 417
418 418 changeset: 5:d8cbc61dbaa6
419 419 branch: a
420 420 parent: 2:881fe2b92ad0
421 421 user: test
422 422 date: Thu Jan 01 00:00:04 1970 +0000
423 423 summary: Adding b branch head 2
424 424
425 425 changeset: 0:19709c5a4e75
426 426 user: test
427 427 date: Thu Jan 01 00:00:00 1970 +0000
428 428 summary: Adding root node
429 429
430 430
431 431 branch default
432 432
433 433 $ hg heads default
434 434 changeset: 0:19709c5a4e75
435 435 user: test
436 436 date: Thu Jan 01 00:00:00 1970 +0000
437 437 summary: Adding root node
438 438
439 439
440 440 branch a
441 441
442 442 $ hg heads a
443 443 changeset: 5:d8cbc61dbaa6
444 444 branch: a
445 445 parent: 2:881fe2b92ad0
446 446 user: test
447 447 date: Thu Jan 01 00:00:04 1970 +0000
448 448 summary: Adding b branch head 2
449 449
450 450 $ hg heads --active a
451 451 no open branch heads found on branches a
452 452 [1]
453 453
454 454 branch b
455 455
456 456 $ hg heads b
457 457 changeset: 13:e23b5505d1ad
458 458 branch: b
459 459 tag: tip
460 460 user: test
461 461 date: Thu Jan 01 00:00:09 1970 +0000
462 462 summary: reopen branch with a change
463 463
464 464 $ hg heads --closed b
465 465 changeset: 13:e23b5505d1ad
466 466 branch: b
467 467 tag: tip
468 468 user: test
469 469 date: Thu Jan 01 00:00:09 1970 +0000
470 470 summary: reopen branch with a change
471 471
472 472 changeset: 11:d3f163457ebf
473 473 branch: b
474 474 user: test
475 475 date: Thu Jan 01 00:00:09 1970 +0000
476 476 summary: prune bad branch
477 477
478 478
479 479 reclose branch
480 480
481 481 $ hg up -C c
482 482 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
483 483 $ hg commit -d '9 0' --close-branch -m 'reclosing this branch'
484 484 $ hg branches
485 485 b 13:e23b5505d1ad
486 486 a branch name much longer than the default justification used by branches 7:10ff5895aa57
487 487 a 5:d8cbc61dbaa6 (inactive)
488 488 default 0:19709c5a4e75 (inactive)
489 489 $ hg branches --closed
490 490 b 13:e23b5505d1ad
491 491 a branch name much longer than the default justification used by branches 7:10ff5895aa57
492 492 c 14:f894c25619d3 (closed)
493 493 a 5:d8cbc61dbaa6 (inactive)
494 494 default 0:19709c5a4e75 (inactive)
495 495
496 496 multihead branch
497 497
498 498 $ hg up -C default
499 499 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
500 500 $ hg branch m
501 501 marked working directory as branch m
502 502 $ touch m
503 503 $ hg add m
504 504 $ hg commit -d '10 0' -m 'multihead base'
505 505 $ echo "m1" >m
506 506 $ hg commit -d '10 0' -m 'head 1'
507 507 $ hg up -C '.^'
508 508 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
509 509 $ echo "m2" >m
510 510 $ hg commit -d '10 0' -m 'head 2'
511 511 created new head
512 512 $ hg log -b m
513 513 changeset: 17:df343b0df04f
514 514 branch: m
515 515 tag: tip
516 516 parent: 15:f3447637f53e
517 517 user: test
518 518 date: Thu Jan 01 00:00:10 1970 +0000
519 519 summary: head 2
520 520
521 521 changeset: 16:a58ca5d3bdf3
522 522 branch: m
523 523 user: test
524 524 date: Thu Jan 01 00:00:10 1970 +0000
525 525 summary: head 1
526 526
527 527 changeset: 15:f3447637f53e
528 528 branch: m
529 529 parent: 0:19709c5a4e75
530 530 user: test
531 531 date: Thu Jan 01 00:00:10 1970 +0000
532 532 summary: multihead base
533 533
534 534 $ hg heads --topo m
535 535 changeset: 17:df343b0df04f
536 536 branch: m
537 537 tag: tip
538 538 parent: 15:f3447637f53e
539 539 user: test
540 540 date: Thu Jan 01 00:00:10 1970 +0000
541 541 summary: head 2
542 542
543 543 changeset: 16:a58ca5d3bdf3
544 544 branch: m
545 545 user: test
546 546 date: Thu Jan 01 00:00:10 1970 +0000
547 547 summary: head 1
548 548
549 549 $ hg branches
550 550 m 17:df343b0df04f
551 551 b 13:e23b5505d1ad
552 552 a branch name much longer than the default justification used by branches 7:10ff5895aa57
553 553 a 5:d8cbc61dbaa6 (inactive)
554 554 default 0:19709c5a4e75 (inactive)
555 555
556 556 partially merge multihead branch
557 557
558 558 $ hg up -C default
559 559 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
560 560 $ hg branch md
561 561 marked working directory as branch md
562 562 $ hg merge m
563 563 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
564 564 (branch merge, don't forget to commit)
565 565 $ hg commit -d '11 0' -m 'merge head 2'
566 566 $ hg heads --topo m
567 567 changeset: 16:a58ca5d3bdf3
568 568 branch: m
569 569 user: test
570 570 date: Thu Jan 01 00:00:10 1970 +0000
571 571 summary: head 1
572 572
573 573 $ hg branches
574 574 md 18:c914c99f1fbb
575 575 m 17:df343b0df04f
576 576 b 13:e23b5505d1ad
577 577 a branch name much longer than the default justification used by branches 7:10ff5895aa57
578 578 a 5:d8cbc61dbaa6 (inactive)
579 579 default 0:19709c5a4e75 (inactive)
580 580
581 581 partially close multihead branch
582 582
583 583 $ hg up -C a58ca5d3bdf3
584 584 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
585 585 $ hg commit -d '12 0' -m 'close head 1' --close-branch
586 586 $ hg heads --topo m
587 587 changeset: 19:cd21a80baa3d
588 588 branch: m
589 589 tag: tip
590 590 parent: 16:a58ca5d3bdf3
591 591 user: test
592 592 date: Thu Jan 01 00:00:12 1970 +0000
593 593 summary: close head 1
594 594
595 595 $ hg branches
596 596 md 18:c914c99f1fbb
597 597 b 13:e23b5505d1ad
598 598 a branch name much longer than the default justification used by branches 7:10ff5895aa57
599 599 m 17:df343b0df04f (inactive)
600 600 a 5:d8cbc61dbaa6 (inactive)
601 601 default 0:19709c5a4e75 (inactive)
602 602
603 603 default branch colors:
604 604
605 605 $ cat <<EOF >> $HGRCPATH
606 606 > [extensions]
607 607 > color =
608 608 > [color]
609 609 > mode = ansi
610 610 > EOF
611 611
612 612 $ hg up -C b
613 613 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
614 614 $ hg branches --color=always
615 615 \x1b[0;0mmd\x1b[0m\x1b[0;33m 18:c914c99f1fbb\x1b[0m (esc)
616 616 \x1b[0;32mb\x1b[0m\x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
617 617 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;33m 7:10ff5895aa57\x1b[0m (esc)
618 618 \x1b[0;0mm\x1b[0m\x1b[0;33m 17:df343b0df04f\x1b[0m (inactive) (esc)
619 619 \x1b[0;0ma\x1b[0m\x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
620 620 \x1b[0;0mdefault\x1b[0m\x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
621 621
622 622 default closed branch color:
623 623
624 624 $ hg branches --color=always --closed
625 625 \x1b[0;0mmd\x1b[0m\x1b[0;33m 18:c914c99f1fbb\x1b[0m (esc)
626 626 \x1b[0;32mb\x1b[0m\x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
627 627 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;33m 7:10ff5895aa57\x1b[0m (esc)
628 628 \x1b[0;0mm\x1b[0m\x1b[0;33m 17:df343b0df04f\x1b[0m (inactive) (esc)
629 629 \x1b[0;30;1mc\x1b[0m\x1b[0;33m 14:f894c25619d3\x1b[0m (closed) (esc)
630 630 \x1b[0;0ma\x1b[0m\x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
631 631 \x1b[0;0mdefault\x1b[0m\x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
632 632
633 633 $ cat <<EOF >> $HGRCPATH
634 634 > [extensions]
635 635 > color =
636 636 > [color]
637 637 > branches.active = green
638 638 > branches.closed = blue
639 639 > branches.current = red
640 640 > branches.inactive = magenta
641 641 > log.changeset = cyan
642 642 > EOF
643 643
644 644 custom branch colors:
645 645
646 646 $ hg branches --color=always
647 647 \x1b[0;32mmd\x1b[0m\x1b[0;36m 18:c914c99f1fbb\x1b[0m (esc)
648 648 \x1b[0;31mb\x1b[0m\x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
649 649 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;36m 7:10ff5895aa57\x1b[0m (esc)
650 650 \x1b[0;35mm\x1b[0m\x1b[0;36m 17:df343b0df04f\x1b[0m (inactive) (esc)
651 651 \x1b[0;35ma\x1b[0m\x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
652 652 \x1b[0;35mdefault\x1b[0m\x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
653 653
654 654 custom closed branch color:
655 655
656 656 $ hg branches --color=always --closed
657 657 \x1b[0;32mmd\x1b[0m\x1b[0;36m 18:c914c99f1fbb\x1b[0m (esc)
658 658 \x1b[0;31mb\x1b[0m\x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
659 659 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m\x1b[0;36m 7:10ff5895aa57\x1b[0m (esc)
660 660 \x1b[0;35mm\x1b[0m\x1b[0;36m 17:df343b0df04f\x1b[0m (inactive) (esc)
661 661 \x1b[0;34mc\x1b[0m\x1b[0;36m 14:f894c25619d3\x1b[0m (closed) (esc)
662 662 \x1b[0;35ma\x1b[0m\x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
663 663 \x1b[0;35mdefault\x1b[0m\x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
664 664
665 665 template output:
666 666
667 667 $ hg branches -Tjson --closed
668 668 [
669 669 {
670 670 "active": true,
671 671 "branch": "md",
672 672 "closed": false,
673 673 "current": false,
674 674 "node": "c914c99f1fbb2b1d785a0a939ed3f67275df18e9",
675 675 "rev": 18
676 676 },
677 677 {
678 678 "active": true,
679 679 "branch": "b",
680 680 "closed": false,
681 681 "current": true,
682 682 "node": "e23b5505d1ad24aab6f84fd8c7cb8cd8e5e93be0",
683 683 "rev": 13
684 684 },
685 685 {
686 686 "active": true,
687 687 "branch": "a branch name much longer than the default justification used by branches",
688 688 "closed": false,
689 689 "current": false,
690 690 "node": "10ff5895aa5793bd378da574af8cec8ea408d831",
691 691 "rev": 7
692 692 },
693 693 {
694 694 "active": false,
695 695 "branch": "m",
696 696 "closed": false,
697 697 "current": false,
698 698 "node": "df343b0df04feb2a946cd4b6e9520e552fef14ee",
699 699 "rev": 17
700 700 },
701 701 {
702 702 "active": false,
703 703 "branch": "c",
704 704 "closed": true,
705 705 "current": false,
706 706 "node": "f894c25619d3f1484639d81be950e0a07bc6f1f6",
707 707 "rev": 14
708 708 },
709 709 {
710 710 "active": false,
711 711 "branch": "a",
712 712 "closed": false,
713 713 "current": false,
714 714 "node": "d8cbc61dbaa6dc817175d1e301eecb863f280832",
715 715 "rev": 5
716 716 },
717 717 {
718 718 "active": false,
719 719 "branch": "default",
720 720 "closed": false,
721 721 "current": false,
722 722 "node": "19709c5a4e75bf938f8e349aff97438539bb729e",
723 723 "rev": 0
724 724 }
725 725 ]
726 726
727 727 $ hg branches --closed -T '{if(closed, "{branch}\n")}'
728 728 c
729 729
730 730 $ hg branches -T '{word(0, branch)}: {desc|firstline}\n'
731 731 md: merge head 2
732 732 b: reopen branch with a change
733 733 a: Adding d branch
734 734 m: head 2
735 735 a: Adding b branch head 2
736 736 default: Adding root node
737 737
738 738 $ cat <<'EOF' > "$TESTTMP/map-myjson"
739 739 > docheader = '\{\n'
740 740 > docfooter = '\n}\n'
741 741 > separator = ',\n'
742 742 > branches = ' {dict(branch, node|short)|json}'
743 743 > EOF
744 744 $ hg branches -T "$TESTTMP/map-myjson"
745 745 {
746 746 {"branch": "md", "node": "c914c99f1fbb"},
747 747 {"branch": "b", "node": "e23b5505d1ad"},
748 748 {"branch": "a branch *", "node": "10ff5895aa57"}, (glob)
749 749 {"branch": "m", "node": "df343b0df04f"},
750 750 {"branch": "a", "node": "d8cbc61dbaa6"},
751 751 {"branch": "default", "node": "19709c5a4e75"}
752 752 }
753 753
754 754 $ cat <<'EOF' >> .hg/hgrc
755 755 > [templates]
756 756 > myjson = ' {dict(branch, node|short)|json}'
757 757 > myjson:docheader = '\{\n'
758 758 > myjson:docfooter = '\n}\n'
759 759 > myjson:separator = ',\n'
760 760 > EOF
761 761 $ hg branches -T myjson
762 762 {
763 763 {"branch": "md", "node": "c914c99f1fbb"},
764 764 {"branch": "b", "node": "e23b5505d1ad"},
765 765 {"branch": "a branch *", "node": "10ff5895aa57"}, (glob)
766 766 {"branch": "m", "node": "df343b0df04f"},
767 767 {"branch": "a", "node": "d8cbc61dbaa6"},
768 768 {"branch": "default", "node": "19709c5a4e75"}
769 769 }
770 770
771 771 $ cat <<'EOF' >> .hg/hgrc
772 772 > [templates]
773 773 > :docheader = 'should not be selected as a docheader for literal templates\n'
774 774 > EOF
775 775 $ hg branches -T '{branch}\n'
776 776 md
777 777 b
778 778 a branch name much longer than the default justification used by branches
779 779 m
780 780 a
781 781 default
782 782
783 783 Tests of revision branch name caching
784 784
785 785 We rev branch cache is updated automatically. In these tests we use a trick to
786 786 trigger rebuilds. We remove the branch head cache and run 'hg head' to cause a
787 787 rebuild that also will populate the rev branch cache.
788 788
789 789 revision branch cache is created when building the branch head cache
790 790 $ rm -rf .hg/cache; hg head a -T '{rev}\n'
791 791 5
792 792 $ f --hexdump --size .hg/cache/rbc-*
793 793 .hg/cache/rbc-names-v2: size=92
794 794 0000: 64 65 66 61 75 6c 74 00 61 00 62 00 63 00 61 20 |default.a.b.c.a |
795 795 0010: 62 72 61 6e 63 68 20 6e 61 6d 65 20 6d 75 63 68 |branch name much|
796 796 0020: 20 6c 6f 6e 67 65 72 20 74 68 61 6e 20 74 68 65 | longer than the|
797 797 0030: 20 64 65 66 61 75 6c 74 20 6a 75 73 74 69 66 69 | default justifi|
798 798 0040: 63 61 74 69 6f 6e 20 75 73 65 64 20 62 79 20 62 |cation used by b|
799 799 0050: 72 61 6e 63 68 65 73 00 6d 00 6d 64 |ranches.m.md|
800 800 .hg/cache/rbc-revs-v2: size=160
801 801 0000: 19 70 9c 5a 00 00 00 00 dd 6b 44 0d 00 00 00 01 |.p.Z.....kD.....|
802 802 0010: 88 1f e2 b9 00 00 00 01 ac 22 03 33 00 00 00 02 |.........".3....|
803 803 0020: ae e3 9c d1 00 00 00 02 d8 cb c6 1d 00 00 00 01 |................|
804 804 0030: 58 97 36 a2 00 00 00 03 10 ff 58 95 00 00 00 04 |X.6.......X.....|
805 805 0040: ee bb 94 44 00 00 00 02 5f 40 61 bb 00 00 00 02 |...D...._@a.....|
806 806 0050: bf be 84 1b 00 00 00 02 d3 f1 63 45 80 00 00 02 |..........cE....|
807 807 0060: e3 d4 9c 05 80 00 00 02 e2 3b 55 05 00 00 00 02 |.........;U.....|
808 808 0070: f8 94 c2 56 80 00 00 03 f3 44 76 37 00 00 00 05 |...V.....Dv7....|
809 809 0080: a5 8c a5 d3 00 00 00 05 df 34 3b 0d 00 00 00 05 |.........4;.....|
810 810 0090: c9 14 c9 9f 00 00 00 06 cd 21 a8 0b 80 00 00 05 |.........!......|
811 811
812 812 no errors when revbranchcache is not writable
813 813
814 814 $ echo >> .hg/cache/rbc-revs-v2
815 815 $ mv .hg/cache/rbc-revs-v2 .hg/cache/rbc-revs-v2_
816 816 $ mkdir .hg/cache/rbc-revs-v2
817 817 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n'
818 818 5
819 819 $ rmdir .hg/cache/rbc-revs-v2
820 820 $ mv .hg/cache/rbc-revs-v2_ .hg/cache/rbc-revs-v2
821 821
822 822 no errors when wlock cannot be acquired
823 823
824 824 #if unix-permissions
825 825 $ mv .hg/cache/rbc-revs-v2 .hg/cache/rbc-revs-v2_
826 826 $ rm -f .hg/cache/branch*
827 827 $ chmod 555 .hg
828 828 $ hg head a -T '{rev}\n'
829 829 5
830 830 $ chmod 755 .hg
831 831 $ mv .hg/cache/rbc-revs-v2_ .hg/cache/rbc-revs-v2
832 832 #endif
833 833
834 834 recovery from invalid cache revs file with trailing data
835 835 $ echo >> .hg/cache/rbc-revs-v2
836 836 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
837 837 5
838 overwriting 0 bytes from 160 in cache/rbc-revs-v2 leaving (2 trailing bytes)
838 cache/rbc-revs-v2 contains 2 unknown trailing bytes
839 839 $ f --size .hg/cache/rbc-revs*
840 840 .hg/cache/rbc-revs-v2: size=162
841 841
842 842 recovery from invalid cache file with partial last record
843 843 $ mv .hg/cache/rbc-revs-v2 .
844 844 $ f -qDB 119 rbc-revs-v2 > .hg/cache/rbc-revs-v2
845 845 $ f --size .hg/cache/rbc-revs*
846 846 .hg/cache/rbc-revs-v2: size=119
847 847 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
848 848 5
849 849 resetting content of cache/rbc-revs-v2
850 850 $ f --size .hg/cache/rbc-revs*
851 851 .hg/cache/rbc-revs-v2: size=160
852 852
853 853 recovery from invalid cache file with missing record - no truncation
854 854 $ mv .hg/cache/rbc-revs-v2 .
855 855 $ f -qDB 112 rbc-revs-v2 > .hg/cache/rbc-revs-v2
856 856 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
857 857 5
858 858 $ f --size .hg/cache/rbc-revs*
859 859 .hg/cache/rbc-revs-v2: size=160
860 860
861 861 recovery from invalid cache file with some bad records
862 862 $ mv .hg/cache/rbc-revs-v2 .
863 863 $ f -qDB 8 rbc-revs-v2 > .hg/cache/rbc-revs-v2
864 864 $ f --size .hg/cache/rbc-revs*
865 865 .hg/cache/rbc-revs-v2: size=8
866 866 $ f -qDB 112 rbc-revs-v2 >> .hg/cache/rbc-revs-v2
867 867 $ f --size .hg/cache/rbc-revs*
868 868 .hg/cache/rbc-revs-v2: size=120
869 869 $ hg log -r 'branch(.)' -T '{rev} ' --debug
870 870 history modification detected - truncating revision branch cache to revision * (glob)
871 871 history modification detected - truncating revision branch cache to revision 1
872 872 3 4 8 9 10 11 12 13 resetting content of cache/rbc-revs-v2
873 873 $ rm -f .hg/cache/branch* && hg head a -T '{rev}\n' --debug
874 874 5
875 875 resetting content of cache/rbc-revs-v2
876 876 $ f --size --hexdump --bytes=16 .hg/cache/rbc-revs*
877 877 .hg/cache/rbc-revs-v2: size=160
878 878 0000: 19 70 9c 5a 00 00 00 00 dd 6b 44 0d 00 00 00 01 |.p.Z.....kD.....|
879 879
880 880 Smoothly reuse "v1" format if no v2 exists
881 881 ------------------------------------------
882 882
883 883 read only operation with valid data
884 884 (actively rewrite data)
885 885
886 886 $ rm .hg/cache/rbc-names-v2
887 887 $ rm .hg/cache/rbc-revs-v2
888 888 $ rm .hg/cache/branch*
889 889 $ hg head a -T '{rev}\n' --debug
890 890 5
891 891 $ mv .hg/cache/rbc-names-v2 .hg/cache/rbc-names-v1
892 892 $ mv .hg/cache/rbc-revs-v2 .hg/cache/rbc-revs-v1
893 893 $ rm .hg/cache/branch*
894 894 $ hg head a -T '{rev}\n' --debug
895 895 5
896 896 $ f --size .hg/cache/rbc-*-*
897 897 .hg/cache/rbc-names-v1: size=92
898 898 .hg/cache/rbc-names-v2: size=92
899 899 .hg/cache/rbc-revs-v1: size=160
900 900 .hg/cache/rbc-revs-v2: size=160
901 901
902 902
903 903 Write operation write a full v2 files
904 904
905 905 $ mv .hg/cache/rbc-names-v2 .hg/cache/rbc-names-v1
906 906 $ mv .hg/cache/rbc-revs-v2 .hg/cache/rbc-revs-v1
907 907 $ f --size .hg/cache/rbc-*
908 908 .hg/cache/rbc-names-v1: size=92
909 909 .hg/cache/rbc-revs-v1: size=160
910 910 $ hg branch not-here-for-long
911 911 marked working directory as branch not-here-for-long
912 912 $ hg ci -m not-long --debug
913 913 reusing manifest from p1 (no file change)
914 914 committing changelog
915 915 updating the branch cache
916 916 committed changeset * (glob)
917 917 $ f --size .hg/cache/rbc-*
918 918 .hg/cache/rbc-names-v1: size=92
919 919 .hg/cache/rbc-names-v2: size=110
920 920 .hg/cache/rbc-revs-v1: size=160
921 921 .hg/cache/rbc-revs-v2: size=168
922 922
923 923 So does explicit cache upgrade
924 924 $ mv .hg/cache/rbc-names-v2 .hg/cache/rbc-names-v1
925 925 $ mv .hg/cache/rbc-revs-v2 .hg/cache/rbc-revs-v1
926 926 $ f --size .hg/cache/rbc-*
927 927 .hg/cache/rbc-names-v1: size=110
928 928 .hg/cache/rbc-revs-v1: size=168
929 929 $ hg debugupdatecache
930 930 $ f --size .hg/cache/rbc-*
931 931 .hg/cache/rbc-names-v1: size=110
932 932 .hg/cache/rbc-names-v2: size=110
933 933 .hg/cache/rbc-revs-v1: size=168
934 934 .hg/cache/rbc-revs-v2: size=168
935 935
936 936 With invalid v1 data, we rewrite it too (as v2)
937 937
938 938 $ cp .hg/cache/rbc-names-v2 .hg/cache/rbc-names-v1
939 939 $ mv .hg/cache/rbc-names-v2 .hg/cache/rbc-revs-v1
940 940 $ rm .hg/cache/rbc-revs-v2
941 941 $ rm .hg/cache/branch*
942 942 $
943 943 $ hg head a -T '{rev}\n' --debug
944 944 history modification detected - truncating revision branch cache to revision 0
945 945 5
946 946 $ f --size .hg/cache/rbc-*-*
947 947 .hg/cache/rbc-names-v1: size=110
948 948 .hg/cache/rbc-names-v2: size=110
949 949 .hg/cache/rbc-revs-v1: size=110
950 950 .hg/cache/rbc-revs-v2: size=168
951 951
952 952 cleanup
953 953
954 954 $ hg up -qr '.^'
955 955 $ hg rollback -qf
956 956 $ rm .hg/cache/*
957 957 $ hg debugupdatecache
958 958 $ f --size .hg/cache/rbc-*
959 959 .hg/cache/rbc-names-v2: size=92
960 960 .hg/cache/rbc-revs-v2: size=160
961 961
962 962 cache is updated when committing
963 963 $ hg branch i-will-regret-this
964 964 marked working directory as branch i-will-regret-this
965 965 $ hg ci -m regrets
966 966 $ f --size .hg/cache/rbc-*
967 967 .hg/cache/rbc-names-v2: size=111
968 968 .hg/cache/rbc-revs-v2: size=168
969 969
970 970 update after rollback - the cache will be correct but rbc-names will will still
971 971 contain the branch name even though it no longer is used
972 972 $ hg up -qr '.^'
973 973 $ hg rollback -qf
974 974 $ f --size .hg/cache/rbc-names-*
975 975 .hg/cache/rbc-names-v2: size=111
976 976 $ grep "i-will-regret-this" .hg/cache/rbc-names-* > /dev/null
977 977 $ f --size .hg/cache/rbc-revs-*
978 978 .hg/cache/rbc-revs-v2: size=168
979 979
980 980 cache is updated/truncated when stripping - it is thus very hard to get in a
981 981 situation where the cache is out of sync and the hash check detects it
982 982 $ hg --config extensions.strip= strip -r tip --nob
983 983 $ f --size .hg/cache/rbc-revs*
984 984 .hg/cache/rbc-revs-v2: size=152
985 985
986 986 cache is rebuilt when corruption is detected
987 987 $ echo > .hg/cache/rbc-names-v2
988 988 $ hg log -r '5:&branch(.)' -T '{rev} ' --debug
989 989 referenced branch names not found - rebuilding revision branch cache from scratch
990 990 8 9 10 11 12 13 resetting content of rbc-names-v2
991 991 $ f --size .hg/cache/rbc-names-*
992 992 .hg/cache/rbc-names-v2: size=84
993 993 $ grep "i-will-regret-this" .hg/cache/rbc-names-* > /dev/null
994 994 [1]
995 995 $ f --size .hg/cache/rbc-revs-*
996 996 .hg/cache/rbc-revs-v2: size=152
997 997
998 998 Test that cache files are created and grows correctly:
999 999
1000 1000 $ rm .hg/cache/rbc*
1001 1001 $ hg log -r "5 & branch(5)" -T "{rev}\n"
1002 1002 5
1003 1003
1004 1004 (here v3 is querying branch info for heads so it warm much more of the cache)
1005 1005
1006 1006 #if v2
1007 1007 $ f --size .hg/cache/rbc-*
1008 1008 .hg/cache/rbc-names-v2: size=1
1009 1009 .hg/cache/rbc-revs-v2: size=48
1010 1010 #else
1011 1011 $ f --size .hg/cache/rbc-*
1012 1012 .hg/cache/rbc-names-v2: size=84
1013 1013 .hg/cache/rbc-revs-v2: size=152
1014 1014 #endif
1015 1015
1016 1016 $ cd ..
1017 1017
1018 1018 Test for multiple incorrect branch cache entries:
1019 1019
1020 1020 $ hg init b
1021 1021 $ cd b
1022 1022 $ touch f
1023 1023 $ hg ci -Aqmf
1024 1024 $ echo >> f
1025 1025 $ hg ci -Amf
1026 1026 $ hg branch -q branch
1027 1027 $ hg ci -Amf
1028 1028
1029 1029 #if v2
1030 1030
1031 1031 $ f --size --sha256 .hg/cache/rbc-*
1032 1032 .hg/cache/rbc-names-v2: size=14, sha256=d376f7eea9a7e28fac6470e78dae753c81a5543c9ad436e96999590e004a281c
1033 1033 .hg/cache/rbc-revs-v2: size=24, sha256=ec89032fd4e66e7282cb6e403848c681a855a9c36c6b44d19179218553b78779
1034 1034
1035 1035 $ : > .hg/cache/rbc-revs-v2
1036 1036
1037 1037 No superfluous rebuilding of cache:
1038 1038 $ hg log -r "branch(null)&branch(branch)" --debug
1039 1039 $ f --size --sha256 .hg/cache/rbc-*
1040 1040 .hg/cache/rbc-names-v2: size=14, sha256=d376f7eea9a7e28fac6470e78dae753c81a5543c9ad436e96999590e004a281c
1041 1041 .hg/cache/rbc-revs-v2: size=24, sha256=ec89032fd4e66e7282cb6e403848c681a855a9c36c6b44d19179218553b78779
1042 1042 #endif
1043 1043
1044 1044 $ cd ..
1045 1045
1046 1046 Test to make sure that `--close-branch` only works on a branch head:
1047 1047 --------------------------------------------------------------------
1048 1048 $ hg init closebranch
1049 1049 $ cd closebranch
1050 1050 $ for ch in a b c; do
1051 1051 > echo $ch > $ch
1052 1052 > hg add $ch
1053 1053 > hg ci -m "added "$ch
1054 1054 > done;
1055 1055
1056 1056 $ hg up -r "desc('added b')"
1057 1057 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1058 1058
1059 1059 trying to close branch from a cset which is not a branch head
1060 1060 it should abort:
1061 1061 $ hg ci -m "closing branch" --close-branch
1062 1062 abort: can only close branch heads
1063 1063 (use --force-close-branch to close branch from a non-head changeset)
1064 1064 [10]
1065 1065
1066 1066 $ hg up 0
1067 1067 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1068 1068 $ hg log -GT "{rev}: {node|short} {desc|firstline}\n\t{branch}\n\n"
1069 1069 o 2: 155349b645be added c
1070 1070 | default
1071 1071 |
1072 1072 o 1: 5f6d8a4bf34a added b
1073 1073 | default
1074 1074 |
1075 1075 @ 0: 9092f1db7931 added a
1076 1076 default
1077 1077
1078 1078 Test --force-close-branch to close a branch from a non-head changeset:
1079 1079 ---------------------------------------------------------------------
1080 1080
1081 1081 $ hg show stack --config extensions.show=
1082 1082 o 1553 added c
1083 1083 o 5f6d added b
1084 1084 @ 9092 added a
1085 1085
1086 1086 $ hg ci -m "branch closed" --close-branch
1087 1087 abort: can only close branch heads
1088 1088 (use --force-close-branch to close branch from a non-head changeset)
1089 1089 [10]
1090 1090
1091 1091 $ hg ci -m "branch closed" --force-close-branch
1092 1092 created new head
1093 1093 $ cd ..
1094 1094
1095 1095 Test various special cases for the branchmap
1096 1096 --------------------------------------------
1097 1097
1098 1098 Basic fork of the same branch
1099 1099
1100 1100 $ hg init branchmap-testing1
1101 1101 $ cd branchmap-testing1
1102 1102 $ hg debugbuild '@A . :base . :p1 *base /p1'
1103 1103 $ hg log -G
1104 1104 o changeset: 3:71ca9a6d524e
1105 1105 |\ branch: A
1106 1106 | | tag: tip
1107 1107 | | parent: 2:a3b807b3ff0b
1108 1108 | | parent: 1:99ba08759bc7
1109 1109 | | user: debugbuilddag
1110 1110 | | date: Thu Jan 01 00:00:03 1970 +0000
1111 1111 | | summary: r3
1112 1112 | |
1113 1113 | o changeset: 2:a3b807b3ff0b
1114 1114 | | branch: A
1115 1115 | | parent: 0:2ab8003a1750
1116 1116 | | user: debugbuilddag
1117 1117 | | date: Thu Jan 01 00:00:02 1970 +0000
1118 1118 | | summary: r2
1119 1119 | |
1120 1120 o | changeset: 1:99ba08759bc7
1121 1121 |/ branch: A
1122 1122 | tag: p1
1123 1123 | user: debugbuilddag
1124 1124 | date: Thu Jan 01 00:00:01 1970 +0000
1125 1125 | summary: r1
1126 1126 |
1127 1127 o changeset: 0:2ab8003a1750
1128 1128 branch: A
1129 1129 tag: base
1130 1130 user: debugbuilddag
1131 1131 date: Thu Jan 01 00:00:00 1970 +0000
1132 1132 summary: r0
1133 1133
1134 1134 $ hg branches
1135 1135 A 3:71ca9a6d524e
1136 1136 $ hg clone -r 1 -r 2 . ../branchmap-testing1-clone
1137 1137 adding changesets
1138 1138 adding manifests
1139 1139 adding file changes
1140 1140 added 3 changesets with 0 changes to 0 files (+1 heads)
1141 1141 new changesets 2ab8003a1750:a3b807b3ff0b
1142 1142 updating to branch A
1143 1143 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1144 1144 $ cd ../branchmap-testing1-clone
1145 1145 $ hg pull ../branchmap-testing1
1146 1146 pulling from ../branchmap-testing1
1147 1147 searching for changes
1148 1148 adding changesets
1149 1149 adding manifests
1150 1150 adding file changes
1151 1151 added 1 changesets with 0 changes to 0 files (-1 heads)
1152 1152 new changesets 71ca9a6d524e
1153 1153 (run 'hg update' to get a working copy)
1154 1154 $ hg branches
1155 1155 A 3:71ca9a6d524e
1156 1156 $ cd ..
1157 1157
1158 1158 Switching to a different branch and back
1159 1159
1160 1160 $ hg init branchmap-testing2
1161 1161 $ cd branchmap-testing2
1162 1162 $ hg debugbuild '@A . @B . @A .'
1163 1163 $ hg log -G
1164 1164 o changeset: 2:9699e9f260b5
1165 1165 | branch: A
1166 1166 | tag: tip
1167 1167 | user: debugbuilddag
1168 1168 | date: Thu Jan 01 00:00:02 1970 +0000
1169 1169 | summary: r2
1170 1170 |
1171 1171 o changeset: 1:0bc7d348d965
1172 1172 | branch: B
1173 1173 | user: debugbuilddag
1174 1174 | date: Thu Jan 01 00:00:01 1970 +0000
1175 1175 | summary: r1
1176 1176 |
1177 1177 o changeset: 0:2ab8003a1750
1178 1178 branch: A
1179 1179 user: debugbuilddag
1180 1180 date: Thu Jan 01 00:00:00 1970 +0000
1181 1181 summary: r0
1182 1182
1183 1183 $ hg branches
1184 1184 A 2:9699e9f260b5
1185 1185 B 1:0bc7d348d965 (inactive)
1186 1186 $ hg clone -r 1 . ../branchmap-testing2-clone
1187 1187 adding changesets
1188 1188 adding manifests
1189 1189 adding file changes
1190 1190 added 2 changesets with 0 changes to 0 files
1191 1191 new changesets 2ab8003a1750:0bc7d348d965
1192 1192 updating to branch B
1193 1193 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1194 1194 $ cd ../branchmap-testing2-clone
1195 1195 $ hg pull ../branchmap-testing2
1196 1196 pulling from ../branchmap-testing2
1197 1197 searching for changes
1198 1198 adding changesets
1199 1199 adding manifests
1200 1200 adding file changes
1201 1201 added 1 changesets with 0 changes to 0 files
1202 1202 new changesets 9699e9f260b5
1203 1203 (run 'hg update' to get a working copy)
1204 1204 $ hg branches
1205 1205 A 2:9699e9f260b5
1206 1206 B 1:0bc7d348d965 (inactive)
1207 1207 $ cd ..
1208 1208
1209 1209 A fork on a branch switching to a different branch and back
1210 1210 is still collecting the fork.
1211 1211
1212 1212 $ hg init branchmap-testing3
1213 1213 $ cd branchmap-testing3
1214 1214 $ hg debugbuild '@A . :base . :p1 *base @B . @A /p1'
1215 1215 $ hg log -G
1216 1216 o changeset: 4:3614a1711d23
1217 1217 |\ branch: A
1218 1218 | | tag: tip
1219 1219 | | parent: 3:e9c8abcf65aa
1220 1220 | | parent: 1:99ba08759bc7
1221 1221 | | user: debugbuilddag
1222 1222 | | date: Thu Jan 01 00:00:04 1970 +0000
1223 1223 | | summary: r4
1224 1224 | |
1225 1225 | o changeset: 3:e9c8abcf65aa
1226 1226 | | branch: B
1227 1227 | | user: debugbuilddag
1228 1228 | | date: Thu Jan 01 00:00:03 1970 +0000
1229 1229 | | summary: r3
1230 1230 | |
1231 1231 | o changeset: 2:a3b807b3ff0b
1232 1232 | | branch: A
1233 1233 | | parent: 0:2ab8003a1750
1234 1234 | | user: debugbuilddag
1235 1235 | | date: Thu Jan 01 00:00:02 1970 +0000
1236 1236 | | summary: r2
1237 1237 | |
1238 1238 o | changeset: 1:99ba08759bc7
1239 1239 |/ branch: A
1240 1240 | tag: p1
1241 1241 | user: debugbuilddag
1242 1242 | date: Thu Jan 01 00:00:01 1970 +0000
1243 1243 | summary: r1
1244 1244 |
1245 1245 o changeset: 0:2ab8003a1750
1246 1246 branch: A
1247 1247 tag: base
1248 1248 user: debugbuilddag
1249 1249 date: Thu Jan 01 00:00:00 1970 +0000
1250 1250 summary: r0
1251 1251
1252 1252 $ hg branches
1253 1253 A 4:3614a1711d23
1254 1254 B 3:e9c8abcf65aa (inactive)
1255 1255 $ hg clone -r 1 -r 3 . ../branchmap-testing3-clone
1256 1256 adding changesets
1257 1257 adding manifests
1258 1258 adding file changes
1259 1259 added 4 changesets with 0 changes to 0 files (+1 heads)
1260 1260 new changesets 2ab8003a1750:e9c8abcf65aa
1261 1261 updating to branch A
1262 1262 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1263 1263 $ cd ../branchmap-testing3-clone
1264 1264 $ hg pull ../branchmap-testing3
1265 1265 pulling from ../branchmap-testing3
1266 1266 searching for changes
1267 1267 adding changesets
1268 1268 adding manifests
1269 1269 adding file changes
1270 1270 added 1 changesets with 0 changes to 0 files (-1 heads)
1271 1271 new changesets 3614a1711d23
1272 1272 (run 'hg update' to get a working copy)
1273 1273 $ hg branches
1274 1274 A 4:3614a1711d23
1275 1275 B 3:e9c8abcf65aa (inactive)
1276 1276 $ cd ..
1277 1277
1278 1278 Intermediary parents are on different branches.
1279 1279
1280 1280 $ hg init branchmap-testing4
1281 1281 $ cd branchmap-testing4
1282 1282 $ hg debugbuild '@A . @B :base . @A :p1 *base @C . @A /p1'
1283 1283 $ hg log -G
1284 1284 o changeset: 4:4bf67499b70a
1285 1285 |\ branch: A
1286 1286 | | tag: tip
1287 1287 | | parent: 3:4a546028fa8f
1288 1288 | | parent: 1:0bc7d348d965
1289 1289 | | user: debugbuilddag
1290 1290 | | date: Thu Jan 01 00:00:04 1970 +0000
1291 1291 | | summary: r4
1292 1292 | |
1293 1293 | o changeset: 3:4a546028fa8f
1294 1294 | | branch: C
1295 1295 | | user: debugbuilddag
1296 1296 | | date: Thu Jan 01 00:00:03 1970 +0000
1297 1297 | | summary: r3
1298 1298 | |
1299 1299 | o changeset: 2:a3b807b3ff0b
1300 1300 | | branch: A
1301 1301 | | parent: 0:2ab8003a1750
1302 1302 | | user: debugbuilddag
1303 1303 | | date: Thu Jan 01 00:00:02 1970 +0000
1304 1304 | | summary: r2
1305 1305 | |
1306 1306 o | changeset: 1:0bc7d348d965
1307 1307 |/ branch: B
1308 1308 | tag: p1
1309 1309 | user: debugbuilddag
1310 1310 | date: Thu Jan 01 00:00:01 1970 +0000
1311 1311 | summary: r1
1312 1312 |
1313 1313 o changeset: 0:2ab8003a1750
1314 1314 branch: A
1315 1315 tag: base
1316 1316 user: debugbuilddag
1317 1317 date: Thu Jan 01 00:00:00 1970 +0000
1318 1318 summary: r0
1319 1319
1320 1320 $ hg branches
1321 1321 A 4:4bf67499b70a
1322 1322 C 3:4a546028fa8f (inactive)
1323 1323 B 1:0bc7d348d965 (inactive)
1324 1324 $ hg clone -r 1 -r 3 . ../branchmap-testing4-clone
1325 1325 adding changesets
1326 1326 adding manifests
1327 1327 adding file changes
1328 1328 added 4 changesets with 0 changes to 0 files (+1 heads)
1329 1329 new changesets 2ab8003a1750:4a546028fa8f
1330 1330 updating to branch B
1331 1331 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1332 1332 $ cd ../branchmap-testing4-clone
1333 1333 $ hg pull ../branchmap-testing4
1334 1334 pulling from ../branchmap-testing4
1335 1335 searching for changes
1336 1336 adding changesets
1337 1337 adding manifests
1338 1338 adding file changes
1339 1339 added 1 changesets with 0 changes to 0 files (-1 heads)
1340 1340 new changesets 4bf67499b70a
1341 1341 (run 'hg update' to get a working copy)
1342 1342 $ hg branches
1343 1343 A 4:4bf67499b70a
1344 1344 C 3:4a546028fa8f (inactive)
1345 1345 B 1:0bc7d348d965 (inactive)
1346 1346 $ cd ..
1347 1347
1348 1348 Check that the cache are not written too early
1349 1349 ----------------------------------------------
1350 1350
1351 1351 $ hg log -R branchmap-testing1 -G
1352 1352 o changeset: 3:71ca9a6d524e
1353 1353 |\ branch: A
1354 1354 | | tag: tip
1355 1355 | | parent: 2:a3b807b3ff0b
1356 1356 | | parent: 1:99ba08759bc7
1357 1357 | | user: debugbuilddag
1358 1358 | | date: Thu Jan 01 00:00:03 1970 +0000
1359 1359 | | summary: r3
1360 1360 | |
1361 1361 | o changeset: 2:a3b807b3ff0b
1362 1362 | | branch: A
1363 1363 | | parent: 0:2ab8003a1750
1364 1364 | | user: debugbuilddag
1365 1365 | | date: Thu Jan 01 00:00:02 1970 +0000
1366 1366 | | summary: r2
1367 1367 | |
1368 1368 o | changeset: 1:99ba08759bc7
1369 1369 |/ branch: A
1370 1370 | tag: p1
1371 1371 | user: debugbuilddag
1372 1372 | date: Thu Jan 01 00:00:01 1970 +0000
1373 1373 | summary: r1
1374 1374 |
1375 1375 o changeset: 0:2ab8003a1750
1376 1376 branch: A
1377 1377 tag: base
1378 1378 user: debugbuilddag
1379 1379 date: Thu Jan 01 00:00:00 1970 +0000
1380 1380 summary: r0
1381 1381
1382 1382 $ hg bundle -R branchmap-testing1 --base 1 bundle.hg --rev 'head()'
1383 1383 2 changesets found
1384 1384
1385 1385 Unbundling revision should warm the served cache
1386 1386
1387 1387 $ hg clone branchmap-testing1 --rev 1 branchmap-update-01
1388 1388 adding changesets
1389 1389 adding manifests
1390 1390 adding file changes
1391 1391 added 2 changesets with 0 changes to 0 files
1392 1392 new changesets 2ab8003a1750:99ba08759bc7
1393 1393 updating to branch A
1394 1394 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1395 1395 #if v3
1396 1396 $ cat branchmap-update-01/.hg/cache/branch3-exp-base
1397 1397 tip-node=99ba08759bc7f6fdbe5304e83d0387f35c082479 tip-rev=1 topo-mode=pure
1398 1398 A
1399 1399 #else
1400 1400 $ cat branchmap-update-01/.hg/cache/branch2-base
1401 1401 99ba08759bc7f6fdbe5304e83d0387f35c082479 1
1402 1402 99ba08759bc7f6fdbe5304e83d0387f35c082479 o A
1403 1403 #endif
1404 1404 $ hg -R branchmap-update-01 unbundle bundle.hg
1405 1405 adding changesets
1406 1406 adding manifests
1407 1407 adding file changes
1408 1408 added 2 changesets with 0 changes to 0 files
1409 1409 new changesets a3b807b3ff0b:71ca9a6d524e (2 drafts)
1410 1410 (run 'hg update' to get a working copy)
1411 1411 #if v3
1412 1412 $ cat branchmap-update-01/.hg/cache/branch3-exp-served
1413 1413 tip-node=71ca9a6d524ed3c2a215119b2086ac3b8c4c8286 tip-rev=3 topo-mode=pure
1414 1414 A
1415 1415 #else
1416 1416 $ cat branchmap-update-01/.hg/cache/branch2-served
1417 1417 71ca9a6d524ed3c2a215119b2086ac3b8c4c8286 3
1418 1418 71ca9a6d524ed3c2a215119b2086ac3b8c4c8286 o A
1419 1419 #endif
1420 1420
1421 1421 aborted Unbundle should not update the on disk cache
1422 1422
1423 1423 $ cat >> simplehook.py << EOF
1424 1424 > import sys
1425 1425 > from mercurial import node
1426 1426 > from mercurial import branchmap
1427 1427 > def hook(ui, repo, *args, **kwargs):
1428 1428 > s = repo.filtered(b"served")
1429 1429 > s.branchmap()
1430 1430 > return 1
1431 1431 > EOF
1432 1432 $ hg clone branchmap-testing1 --rev 1 branchmap-update-02
1433 1433 adding changesets
1434 1434 adding manifests
1435 1435 adding file changes
1436 1436 added 2 changesets with 0 changes to 0 files
1437 1437 new changesets 2ab8003a1750:99ba08759bc7
1438 1438 updating to branch A
1439 1439 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1440 1440
1441 1441 #if v3
1442 1442 $ cat branchmap-update-02/.hg/cache/branch3-exp-base
1443 1443 tip-node=99ba08759bc7f6fdbe5304e83d0387f35c082479 tip-rev=1 topo-mode=pure
1444 1444 A
1445 1445 #else
1446 1446 $ cat branchmap-update-02/.hg/cache/branch2-base
1447 1447 99ba08759bc7f6fdbe5304e83d0387f35c082479 1
1448 1448 99ba08759bc7f6fdbe5304e83d0387f35c082479 o A
1449 1449 #endif
1450 1450 $ hg -R branchmap-update-02 unbundle bundle.hg --config "hooks.pretxnclose=python:$TESTTMP/simplehook.py:hook"
1451 1451 adding changesets
1452 1452 adding manifests
1453 1453 adding file changes
1454 1454 transaction abort!
1455 1455 rollback completed
1456 1456 abort: pretxnclose hook failed
1457 1457 [40]
1458 1458 #if v3
1459 1459 $ cat branchmap-update-02/.hg/cache/branch3-exp-base
1460 1460 tip-node=99ba08759bc7f6fdbe5304e83d0387f35c082479 tip-rev=1 topo-mode=pure
1461 1461 A
1462 1462 #else
1463 1463 $ cat branchmap-update-02/.hg/cache/branch2-base
1464 1464 99ba08759bc7f6fdbe5304e83d0387f35c082479 1
1465 1465 99ba08759bc7f6fdbe5304e83d0387f35c082479 o A
1466 1466 #endif
General Comments 0
You need to be logged in to leave comments. Login now