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