|
@@
-360,6
+360,7
b' class localrepository(repo.repository):'
|
|
360
|
return self.nodetagscache.get(node, [])
|
|
360
|
return self.nodetagscache.get(node, [])
|
|
361
|
|
|
361
|
|
|
362
|
def _branchtags(self, partial, lrev):
|
|
362
|
def _branchtags(self, partial, lrev):
|
|
|
|
|
363
|
# TODO: rename this function?
|
|
363
|
tiprev = len(self) - 1
|
|
364
|
tiprev = len(self) - 1
|
|
364
|
if lrev != tiprev:
|
|
365
|
if lrev != tiprev:
|
|
365
|
self._updatebranchcache(partial, lrev+1, tiprev+1)
|
|
366
|
self._updatebranchcache(partial, lrev+1, tiprev+1)
|
|
@@
-367,7
+368,7
b' class localrepository(repo.repository):'
|
|
367
|
|
|
368
|
|
|
368
|
return partial
|
|
369
|
return partial
|
|
369
|
|
|
370
|
|
|
370
|
def branchtags(self):
|
|
371
|
def _branchheads(self):
|
|
371
|
tip = self.changelog.tip()
|
|
372
|
tip = self.changelog.tip()
|
|
372
|
if self.branchcache is not None and self._branchcachetip == tip:
|
|
373
|
if self.branchcache is not None and self._branchcachetip == tip:
|
|
373
|
return self.branchcache
|
|
374
|
return self.branchcache
|
|
@@
-385,18
+386,25
b' class localrepository(repo.repository):'
|
|
385
|
partial = self._ubranchcache
|
|
386
|
partial = self._ubranchcache
|
|
386
|
|
|
387
|
|
|
387
|
self._branchtags(partial, lrev)
|
|
388
|
self._branchtags(partial, lrev)
|
|
|
|
|
389
|
# this private cache holds all heads (not just tips)
|
|
|
|
|
390
|
self._ubranchcache = partial
|
|
388
|
|
|
391
|
|
|
389
|
# the branch cache is stored on disk as UTF-8, but in the local
|
|
392
|
# the branch cache is stored on disk as UTF-8, but in the local
|
|
390
|
# charset internally
|
|
393
|
# charset internally
|
|
391
|
for k, v in partial.iteritems():
|
|
394
|
for k, v in partial.iteritems():
|
|
392
|
self.branchcache[util.tolocal(k)] = v
|
|
395
|
self.branchcache[util.tolocal(k)] = v
|
|
393
|
self._ubranchcache = partial
|
|
|
|
|
394
|
return self.branchcache
|
|
396
|
return self.branchcache
|
|
395
|
|
|
397
|
|
|
|
|
|
398
|
|
|
|
|
|
399
|
def branchtags(self):
|
|
|
|
|
400
|
'''return a dict where branch names map to the tipmost head of
|
|
|
|
|
401
|
the branch'''
|
|
|
|
|
402
|
return dict([(k, v[-1]) for (k, v) in self._branchheads().iteritems()])
|
|
|
|
|
403
|
|
|
396
|
def _readbranchcache(self):
|
|
404
|
def _readbranchcache(self):
|
|
397
|
partial = {}
|
|
405
|
partial = {}
|
|
398
|
try:
|
|
406
|
try:
|
|
399
|
f = self.opener("branch.cache")
|
|
407
|
f = self.opener("branchheads.cache")
|
|
400
|
lines = f.read().split('\n')
|
|
408
|
lines = f.read().split('\n')
|
|
401
|
f.close()
|
|
409
|
f.close()
|
|
402
|
except (IOError, OSError):
|
|
410
|
except (IOError, OSError):
|
|
@@
-411,7
+419,7
b' class localrepository(repo.repository):'
|
|
411
|
for l in lines:
|
|
419
|
for l in lines:
|
|
412
|
if not l: continue
|
|
420
|
if not l: continue
|
|
413
|
node, label = l.split(" ", 1)
|
|
421
|
node, label = l.split(" ", 1)
|
|
414
|
partial[label.strip()] = bin(node)
|
|
422
|
partial.setdefault(label.strip(), []).append(bin(node))
|
|
415
|
except KeyboardInterrupt:
|
|
423
|
except KeyboardInterrupt:
|
|
416
|
raise
|
|
424
|
raise
|
|
417
|
except Exception, inst:
|
|
425
|
except Exception, inst:
|
|
@@
-422,10
+430,11
b' class localrepository(repo.repository):'
|
|
422
|
|
|
430
|
|
|
423
|
def _writebranchcache(self, branches, tip, tiprev):
|
|
431
|
def _writebranchcache(self, branches, tip, tiprev):
|
|
424
|
try:
|
|
432
|
try:
|
|
425
|
f = self.opener("branch.cache", "w", atomictemp=True)
|
|
433
|
f = self.opener("branchheads.cache", "w", atomictemp=True)
|
|
426
|
f.write("%s %s\n" % (hex(tip), tiprev))
|
|
434
|
f.write("%s %s\n" % (hex(tip), tiprev))
|
|
427
|
for label, node in branches.iteritems():
|
|
435
|
for label, nodes in branches.iteritems():
|
|
428
|
f.write("%s %s\n" % (hex(node), label))
|
|
436
|
for node in nodes:
|
|
|
|
|
437
|
f.write("%s %s\n" % (hex(node), label))
|
|
429
|
f.rename()
|
|
438
|
f.rename()
|
|
430
|
except (IOError, OSError):
|
|
439
|
except (IOError, OSError):
|
|
431
|
pass
|
|
440
|
pass
|
|
@@
-434,7
+443,12
b' class localrepository(repo.repository):'
|
|
434
|
for r in xrange(start, end):
|
|
443
|
for r in xrange(start, end):
|
|
435
|
c = self[r]
|
|
444
|
c = self[r]
|
|
436
|
b = c.branch()
|
|
445
|
b = c.branch()
|
|
437
|
partial[b] = c.node()
|
|
446
|
bheads = partial.setdefault(b, [])
|
|
|
|
|
447
|
bheads.append(c.node())
|
|
|
|
|
448
|
for p in c.parents():
|
|
|
|
|
449
|
pn = p.node()
|
|
|
|
|
450
|
if pn in bheads:
|
|
|
|
|
451
|
bheads.remove(pn)
|
|
438
|
|
|
452
|
|
|
439
|
def lookup(self, key):
|
|
453
|
def lookup(self, key):
|
|
440
|
if isinstance(key, int):
|
|
454
|
if isinstance(key, int):
|
|
@@
-1171,50
+1185,16
b' class localrepository(repo.repository):'
|
|
1171
|
def branchheads(self, branch=None, start=None):
|
|
1185
|
def branchheads(self, branch=None, start=None):
|
|
1172
|
if branch is None:
|
|
1186
|
if branch is None:
|
|
1173
|
branch = self[None].branch()
|
|
1187
|
branch = self[None].branch()
|
|
1174
|
branches = self.branchtags()
|
|
1188
|
branches = self._branchheads()
|
|
1175
|
if branch not in branches:
|
|
1189
|
if branch not in branches:
|
|
1176
|
return []
|
|
1190
|
return []
|
|
1177
|
# The basic algorithm is this:
|
|
1191
|
bheads = branches[branch]
|
|
1178
|
#
|
|
1192
|
# the cache returns heads ordered lowest to highest
|
|
1179
|
# Start from the branch tip since there are no later revisions that can
|
|
1193
|
bheads.reverse()
|
|
1180
|
# possibly be in this branch, and the tip is a guaranteed head.
|
|
|
|
|
1181
|
#
|
|
|
|
|
1182
|
# Remember the tip's parents as the first ancestors, since these by
|
|
|
|
|
1183
|
# definition are not heads.
|
|
|
|
|
1184
|
#
|
|
|
|
|
1185
|
# Step backwards from the brach tip through all the revisions. We are
|
|
|
|
|
1186
|
# guaranteed by the rules of Mercurial that we will now be visiting the
|
|
|
|
|
1187
|
# nodes in reverse topological order (children before parents).
|
|
|
|
|
1188
|
#
|
|
|
|
|
1189
|
# If a revision is one of the ancestors of a head then we can toss it
|
|
|
|
|
1190
|
# out of the ancestors set (we've already found it and won't be
|
|
|
|
|
1191
|
# visiting it again) and put its parents in the ancestors set.
|
|
|
|
|
1192
|
#
|
|
|
|
|
1193
|
# Otherwise, if a revision is in the branch it's another head, since it
|
|
|
|
|
1194
|
# wasn't in the ancestor list of an existing head. So add it to the
|
|
|
|
|
1195
|
# head list, and add its parents to the ancestor list.
|
|
|
|
|
1196
|
#
|
|
|
|
|
1197
|
# If it is not in the branch ignore it.
|
|
|
|
|
1198
|
#
|
|
|
|
|
1199
|
# Once we have a list of heads, use nodesbetween to filter out all the
|
|
|
|
|
1200
|
# heads that cannot be reached from startrev. There may be a more
|
|
|
|
|
1201
|
# efficient way to do this as part of the previous algorithm.
|
|
|
|
|
1202
|
|
|
|
|
|
1203
|
set = util.set
|
|
|
|
|
1204
|
heads = [self.changelog.rev(branches[branch])]
|
|
|
|
|
1205
|
# Don't care if ancestors contains nullrev or not.
|
|
|
|
|
1206
|
ancestors = set(self.changelog.parentrevs(heads[0]))
|
|
|
|
|
1207
|
for rev in xrange(heads[0] - 1, nullrev, -1):
|
|
|
|
|
1208
|
if rev in ancestors:
|
|
|
|
|
1209
|
ancestors.update(self.changelog.parentrevs(rev))
|
|
|
|
|
1210
|
ancestors.remove(rev)
|
|
|
|
|
1211
|
elif self[rev].branch() == branch:
|
|
|
|
|
1212
|
heads.append(rev)
|
|
|
|
|
1213
|
ancestors.update(self.changelog.parentrevs(rev))
|
|
|
|
|
1214
|
heads = [self.changelog.node(rev) for rev in heads]
|
|
|
|
|
1215
|
if start is not None:
|
|
1194
|
if start is not None:
|
|
1216
|
heads = self.changelog.nodesbetween([start], heads)[2]
|
|
1195
|
# filter out the heads that cannot be reached from startrev
|
|
1217
|
return heads
|
|
1196
|
bheads = self.changelog.nodesbetween([start], bheads)[2]
|
|
|
|
|
1197
|
return bheads
|
|
1218
|
|
|
1198
|
|
|
1219
|
def branches(self, nodes):
|
|
1199
|
def branches(self, nodes):
|
|
1220
|
if not nodes:
|
|
1200
|
if not nodes:
|