mirror of
https://github.com/facebook/sapling.git
synced 2025-01-08 14:46:47 +03:00
56338d7005
Summary: They're no longer used. Drop them. The `branchcache` is still somehow used, although it's basically equvilent to `{"default": heads}`. We can probably clean it up further after detached from subversion. Reviewed By: singhsrb Differential Revision: D14180592 fbshipit-source-id: 45230d486f203bf3f55e89ce9eb89e6855e14e54
149 lines
5.1 KiB
Python
149 lines
5.1 KiB
Python
# branchmap.py - logic to computes, maintain and stores branchmap for local repo
|
|
#
|
|
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
from __future__ import absolute_import
|
|
|
|
from . import scmutil
|
|
from .node import nullid, nullrev
|
|
|
|
|
|
def updatecache(repo):
|
|
# Don't write the branchmap if it's disabled.
|
|
# The original logic has unnecessary steps, ex. it calculates the "served"
|
|
# repoview as an attempt to build branchcache for "visible". And then
|
|
# calculates "immutable" for calculating "served", recursively.
|
|
#
|
|
# Just use a shortcut path that construct the branchcache directly.
|
|
partial = repo._branchcaches.get(repo.filtername)
|
|
if partial is None:
|
|
partial = branchcache()
|
|
partial.update(repo, None)
|
|
repo._branchcaches[repo.filtername] = partial
|
|
|
|
|
|
class branchcache(dict):
|
|
"""A dict like object that hold branches heads cache.
|
|
|
|
This cache is used to avoid costly computations to determine all the
|
|
branch heads of a repo.
|
|
|
|
The cache is serialized on disk in the following format:
|
|
|
|
<tip hex node> <tip rev number> [optional filtered repo hex hash]
|
|
<branch head hex node> <open/closed state> <branch name>
|
|
<branch head hex node> <open/closed state> <branch name>
|
|
...
|
|
|
|
The first line is used to check if the cache is still valid. If the
|
|
branch cache is for a filtered repo view, an optional third hash is
|
|
included that hashes the hashes of all filtered revisions.
|
|
|
|
The open/closed state is represented by a single letter 'o' or 'c'.
|
|
This field can be used to avoid changelog reads when determining if a
|
|
branch head closes a branch or not.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
entries=(),
|
|
tipnode=nullid,
|
|
tiprev=nullrev,
|
|
filteredhash=None,
|
|
closednodes=None,
|
|
):
|
|
super(branchcache, self).__init__(entries)
|
|
self.tipnode = tipnode
|
|
self.tiprev = tiprev
|
|
self.filteredhash = filteredhash
|
|
# closednodes is a set of nodes that close their branch. If the branch
|
|
# cache has been updated, it may contain nodes that are no longer
|
|
# heads.
|
|
if closednodes is None:
|
|
self._closednodes = set()
|
|
else:
|
|
self._closednodes = closednodes
|
|
|
|
def validfor(self, repo):
|
|
"""Is the cache content valid regarding a repo
|
|
|
|
- False when cached tipnode is unknown or if we detect a strip.
|
|
- True when cache is up to date or a subset of current repo."""
|
|
try:
|
|
return (self.tipnode == repo.changelog.node(self.tiprev)) and (
|
|
self.filteredhash == scmutil.filteredhash(repo, self.tiprev)
|
|
)
|
|
except IndexError:
|
|
return False
|
|
|
|
def _branchtip(self, heads):
|
|
"""Return tuple with last open head in heads and false,
|
|
otherwise return last closed head and true."""
|
|
tip = heads[-1]
|
|
closed = True
|
|
for h in reversed(heads):
|
|
if h not in self._closednodes:
|
|
tip = h
|
|
closed = False
|
|
break
|
|
return tip, closed
|
|
|
|
def branchtip(self, branch):
|
|
"""Return the tipmost open head on branch head, otherwise return the
|
|
tipmost closed head on branch.
|
|
Raise KeyError for unknown branch."""
|
|
return self._branchtip(self[branch])[0]
|
|
|
|
def iteropen(self, nodes):
|
|
return (n for n in nodes if n not in self._closednodes)
|
|
|
|
def branchheads(self, branch, closed=False):
|
|
heads = self[branch]
|
|
if not closed:
|
|
heads = list(self.iteropen(heads))
|
|
return heads
|
|
|
|
def iterbranches(self):
|
|
for bn, heads in self.iteritems():
|
|
yield (bn, heads) + self._branchtip(heads)
|
|
|
|
def copy(self):
|
|
"""return an deep copy of the branchcache object"""
|
|
return branchcache(
|
|
self, self.tipnode, self.tiprev, self.filteredhash, self._closednodes
|
|
)
|
|
|
|
def update(self, repo, revgen):
|
|
"""Given a branchhead cache, self, that may have extra nodes or be
|
|
missing heads, and a generator of nodes that are strictly a superset of
|
|
heads missing, this function updates self to be correct.
|
|
"""
|
|
# Behave differently if the cache is disabled.
|
|
cl = repo.changelog
|
|
tonode = cl.node
|
|
|
|
if self.tiprev == len(cl) - 1 and self.validfor(repo):
|
|
return
|
|
|
|
# Since we have no branches, the default branch heads are equal to
|
|
# cl.headrevs(). Note: cl.headrevs() is already sorted and it may return
|
|
# -1.
|
|
branchheads = [i for i in cl.headrevs() if i >= 0]
|
|
|
|
if not branchheads:
|
|
if "default" in self:
|
|
del self["default"]
|
|
tiprev = -1
|
|
else:
|
|
self["default"] = [tonode(rev) for rev in branchheads]
|
|
tiprev = branchheads[-1]
|
|
self.tipnode = cl.node(tiprev)
|
|
self.tiprev = tiprev
|
|
self.filteredhash = scmutil.filteredhash(repo, self.tiprev)
|
|
repo.ui.log(
|
|
"branchcache", "perftweaks updated %s branch cache\n", repo.filtername
|
|
)
|