repo: implement headrevs and heads

Summary:
In a future change we want `heads()` to include working parents and bookmarks
unconditionally. That version of `heads()` needs to be used everywhere,
including legacy exchange logic using branchmap.

Since `changelog` does not have access to working copy parents or bookmarks,
let's implement the `heads` and `headrevs` APIs on the `repo` object instead.

The next diff will migrate users of `changelog.headrevs` to `repo.headrevs`.

Reviewed By: markbt

Differential Revision: D18366734

fbshipit-source-id: 8791aaa57efeb1c6d19d6a4502376aeb26832772
This commit is contained in:
Jun Wu 2019-11-07 10:50:10 -08:00 committed by Facebook Github Bot
parent f5b66f78a9
commit e33d12fcb7
3 changed files with 27 additions and 18 deletions

View File

@ -375,11 +375,15 @@ class changelog(revlog.revlog):
def reachableroots(self, minroot, heads, roots, includepath=False):
return self.index.reachableroots2(minroot, heads, roots, includepath)
def headrevs(self, includepublic=True, includedraft=True):
def headrevs(self):
return self._headrevs([])
def _headrevs(self, additionalheads, includepublic=True, includedraft=True):
# This should only be used by repo.heads()
if self._uiconfig.configbool("experimental", "narrow-heads"):
publicnodes, draftnodes = self._remotenodes()
torev = self.nodemap.__getitem__
nodes = []
nodes = list(additionalheads)
if includepublic:
nodes += publicnodes
if includedraft:

View File

@ -242,8 +242,8 @@ class localpeer(repository.peer):
else:
return changegroup.getunbundler("01", cb, None)
def heads(self):
return self._repo.heads()
def heads(self, *args, **kwargs):
return self._repo.heads(*args, **kwargs)
def known(self, nodes):
return self._repo.known(nodes)
@ -2558,15 +2558,24 @@ class localrepository(object):
"""Used by workingctx to clear post-dirstate-status hooks."""
del self._postdsstatus[:]
def heads(self, start=None):
if start is None:
cl = self.changelog
headrevs = reversed(cl.headrevs())
return [cl.node(rev) for rev in headrevs]
def headrevs(self, start=None, includepublic=True, includedraft=True, reverse=True):
if includedraft:
nodes = list(self.nodes("parents() + bookmark()"))
else:
nodes = []
cl = self.changelog
headrevs = cl._headrevs(nodes, includepublic, includedraft)
if start is not None:
startrev = cl.rev(start)
headrevs = [r for r in headrevs if r > startrev]
if reverse:
return list(reversed(headrevs))
else:
return headrevs
heads = self.changelog.heads(start)
# sort the output in rev descending order
return sorted(heads, key=self.changelog.rev, reverse=True)
def heads(self, start=None, includepublic=True, includedraft=True):
headrevs = self.headrevs(start, includepublic, includedraft)
return map(self.changelog.node, headrevs)
def branchheads(self, branch=None, start=None, closed=False):
"""return a (possibly filtered) list of heads for the given branch

View File

@ -321,12 +321,8 @@ class phasecache(object):
def torevs(nodes):
return list(repo.revs("%ln", nodes))
publicheadrevs = cl.headrevs(includepublic=True, includedraft=False)
draftheadrevs = cl.headrevs(includepublic=False, includedraft=True)
# Also consider "." and bookmarks as drafts.
# This prevents them (and their ancestors) from being hidden (secret).
draftheadrevs += list(repo.revs("parents() + bookmark()"))
publicheadrevs = repo.headrevs(includepublic=True, includedraft=False)
draftheadrevs = repo.headrevs(includepublic=False, includedraft=True)
self._publicrevs, self._draftrevs = cl.index2.phasesets(
publicheadrevs, draftheadrevs