sapling/hgext/amend/hiddenoverride.py
Saurabh Singh 6317ba0ca2 amend: replace with the fbamend extension
Summary:
The functionality we care about is provided by the `fbamend`
extension. Therefore, lets replace the `amend` extension with the `fbamend`
extension.

Reviewed By: farnz

Differential Revision: D10320739

fbshipit-source-id: 5700d39f488777fcc4033f60ce0a51cda15ef2ad
2018-10-11 06:59:23 -07:00

135 lines
4.4 KiB
Python

# hiddenoverride.py - lightweight hidden-ness override
#
# Copyright 2017 Facebook, Inc.
#
# 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 hgext import extutil
from mercurial import dispatch, error, extensions, obsolete, repoview, scmutil, util
from mercurial.node import short
def uisetup(ui):
extensions.wrapfunction(repoview, "pinnedrevs", pinnedrevs)
extensions.wrapfunction(dispatch, "runcommand", runcommand)
extensions.wrapfunction(obsolete, "createmarkers", createmarkers)
extensions.wrapfunction(scmutil, "cleanupnodes", cleanupnodes)
def pinnedrevs(orig, repo):
revs = orig(repo)
nodemap = repo.changelog.nodemap
pinnednodes = set(loadpinnednodes(repo))
tounpin = getattr(repo, "_tounpinnodes", set())
pinnednodes -= tounpin
revs.update(nodemap[n] for n in pinnednodes)
return revs
def loadpinnednodes(repo):
"""yield pinned nodes that are obsoleted and should be visible"""
if repo is None or not repo.local():
return
# the "pinned nodes" file name is "obsinhibit" for compatibility reason
content = repo.svfs.tryread("obsinhibit") or ""
unfi = repo.unfiltered()
nodemap = unfi.changelog.nodemap
offset = 0
result = []
while True:
node = content[offset : offset + 20]
if not node:
break
if node in nodemap:
result.append(node)
offset += 20
return result
def shouldpinnodes(repo):
"""get nodes that should be pinned: working parent + bookmarks for now"""
result = set()
if repo and repo.local():
# working copy parent
try:
wnode = repo.localvfs("dirstate").read(20)
result.add(wnode)
except Exception:
pass
# bookmarks
result.update(repo.unfiltered()._bookmarks.values())
return result
def savepinnednodes(repo, newpin, newunpin, fullargs):
# take a narrowed lock so it does not affect repo lock
with extutil.flock(repo.svfs.join("obsinhibit.lock"), "save pinned nodes"):
orignodes = loadpinnednodes(repo)
nodes = set(orignodes)
nodes |= set(newpin)
nodes -= set(newunpin)
with util.atomictempfile(repo.svfs.join("obsinhibit")) as f:
f.write("".join(nodes))
desc = lambda s: [short(n) for n in s]
repo.ui.log(
"pinnednodes",
"pinnednodes: %r newpin=%r newunpin=%r " "before=%r after=%r\n",
fullargs,
desc(newpin),
desc(newunpin),
desc(orignodes),
desc(nodes),
)
def runcommand(orig, lui, repo, cmd, fullargs, *args):
# return directly for non-repo command
if not repo:
return orig(lui, repo, cmd, fullargs, *args)
shouldpinbefore = shouldpinnodes(repo) | set(loadpinnednodes(repo))
result = orig(lui, repo, cmd, fullargs, *args)
# after a command completes, make sure working copy parent and all
# bookmarks get "pinned".
newpin = shouldpinnodes(repo) - shouldpinbefore
newunpin = getattr(repo.unfiltered(), "_tounpinnodes", set())
# filter newpin by obsolte - ex. if newpin is on a non-obsoleted commit,
# ignore it.
if newpin:
unfi = repo.unfiltered()
obsoleted = unfi.revs("obsolete()")
nodemap = unfi.changelog.nodemap
newpin = set(n for n in newpin if n in nodemap and nodemap[n] in obsoleted)
# only do a write if something has changed
if newpin or newunpin:
savepinnednodes(repo, newpin, newunpin, fullargs)
return result
def createmarkers(orig, repo, rels, *args, **kwargs):
# this is a way to unpin revs - precursors are unpinned
# note: hg debugobsolete does not call this function
unfi = repo.unfiltered()
tounpin = getattr(unfi, "_tounpinnodes", set())
for r in rels:
try:
tounpin.add(r[0].node())
except error.RepoLookupError:
pass
unfi._tounpinnodes = tounpin
return orig(repo, rels, *args, **kwargs)
def cleanupnodes(orig, repo, mapping, *args, **kwargs):
# this catches cases where cleanupnodes is called but createmarkers is not
# called. unpin nodes from mapping
unfi = repo.unfiltered()
tounpin = getattr(unfi, "_tounpinnodes", set())
tounpin.update(mapping)
unfi._tounpinnodes = tounpin
return orig(repo, mapping, *args, **kwargs)