2017-07-13 21:04:56 +03:00
|
|
|
# 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
|
|
|
|
|
2018-01-10 02:23:52 +03:00
|
|
|
from hgext import extutil
|
2018-05-30 12:16:33 +03:00
|
|
|
from mercurial import dispatch, error, extensions, obsolete, repoview, scmutil, util
|
2018-07-06 03:45:27 +03:00
|
|
|
from mercurial.node import short
|
2018-05-30 12:16:33 +03:00
|
|
|
|
2017-07-13 21:04:56 +03:00
|
|
|
|
|
|
|
def uisetup(ui):
|
2018-05-30 12:16:33 +03:00
|
|
|
extensions.wrapfunction(repoview, "pinnedrevs", pinnedrevs)
|
|
|
|
extensions.wrapfunction(dispatch, "runcommand", runcommand)
|
|
|
|
extensions.wrapfunction(obsolete, "createmarkers", createmarkers)
|
|
|
|
extensions.wrapfunction(scmutil, "cleanupnodes", cleanupnodes)
|
|
|
|
|
2017-07-13 21:04:56 +03:00
|
|
|
|
|
|
|
def pinnedrevs(orig, repo):
|
|
|
|
revs = orig(repo)
|
|
|
|
nodemap = repo.changelog.nodemap
|
2017-07-20 03:49:21 +03:00
|
|
|
pinnednodes = set(loadpinnednodes(repo))
|
2018-05-30 12:16:33 +03:00
|
|
|
tounpin = getattr(repo, "_tounpinnodes", set())
|
2017-07-20 03:49:21 +03:00
|
|
|
pinnednodes -= tounpin
|
|
|
|
revs.update(nodemap[n] for n in pinnednodes)
|
2017-07-13 21:04:56 +03:00
|
|
|
return revs
|
|
|
|
|
2018-05-30 12:16:33 +03:00
|
|
|
|
2017-07-13 21:04:56 +03:00
|
|
|
def loadpinnednodes(repo):
|
2017-07-21 08:22:38 +03:00
|
|
|
"""yield pinned nodes that are obsoleted and should be visible"""
|
2017-07-13 21:04:56 +03:00
|
|
|
if repo is None or not repo.local():
|
|
|
|
return
|
|
|
|
# the "pinned nodes" file name is "obsinhibit" for compatibility reason
|
2018-05-30 12:16:33 +03:00
|
|
|
content = repo.svfs.tryread("obsinhibit") or ""
|
2017-07-21 08:22:38 +03:00
|
|
|
unfi = repo.unfiltered()
|
|
|
|
nodemap = unfi.changelog.nodemap
|
2017-07-13 21:04:56 +03:00
|
|
|
offset = 0
|
2017-07-21 20:50:30 +03:00
|
|
|
result = []
|
2017-07-13 21:04:56 +03:00
|
|
|
while True:
|
2018-05-30 12:16:33 +03:00
|
|
|
node = content[offset : offset + 20]
|
2017-07-13 21:04:56 +03:00
|
|
|
if not node:
|
|
|
|
break
|
2017-09-26 23:34:34 +03:00
|
|
|
if node in nodemap:
|
2017-07-21 20:50:30 +03:00
|
|
|
result.append(node)
|
2017-07-13 21:04:56 +03:00
|
|
|
offset += 20
|
2017-07-21 20:50:30 +03:00
|
|
|
return result
|
2017-07-13 21:04:56 +03:00
|
|
|
|
2018-05-30 12:16:33 +03:00
|
|
|
|
2017-07-19 02:07:33 +03:00
|
|
|
def shouldpinnodes(repo):
|
|
|
|
"""get nodes that should be pinned: working parent + bookmarks for now"""
|
|
|
|
result = set()
|
2017-07-13 21:04:56 +03:00
|
|
|
if repo and repo.local():
|
2017-07-19 02:07:33 +03:00
|
|
|
# working copy parent
|
2017-07-13 21:04:56 +03:00
|
|
|
try:
|
2018-05-30 12:16:33 +03:00
|
|
|
wnode = repo.vfs("dirstate").read(20)
|
2017-07-19 02:07:33 +03:00
|
|
|
result.add(wnode)
|
2017-07-13 21:04:56 +03:00
|
|
|
except Exception:
|
|
|
|
pass
|
2017-07-19 02:07:33 +03:00
|
|
|
# bookmarks
|
2017-09-26 23:34:34 +03:00
|
|
|
result.update(repo.unfiltered()._bookmarks.values())
|
2017-07-19 02:07:33 +03:00
|
|
|
return result
|
|
|
|
|
2018-05-30 12:16:33 +03:00
|
|
|
|
2017-07-21 20:50:30 +03:00
|
|
|
def savepinnednodes(repo, newpin, newunpin, fullargs):
|
2017-07-19 02:07:33 +03:00
|
|
|
# take a narrowed lock so it does not affect repo lock
|
2018-05-30 12:16:33 +03:00
|
|
|
with extutil.flock(repo.svfs.join("obsinhibit.lock"), "save pinned nodes"):
|
2017-07-21 20:50:30 +03:00
|
|
|
orignodes = loadpinnednodes(repo)
|
|
|
|
nodes = set(orignodes)
|
2017-07-19 02:07:33 +03:00
|
|
|
nodes |= set(newpin)
|
|
|
|
nodes -= set(newunpin)
|
2018-05-30 12:16:33 +03:00
|
|
|
with util.atomictempfile(repo.svfs.join("obsinhibit")) as f:
|
|
|
|
f.write("".join(nodes))
|
2017-07-19 02:07:33 +03:00
|
|
|
|
2017-07-21 20:50:30 +03:00
|
|
|
desc = lambda s: [short(n) for n in s]
|
2018-05-30 12:16:33 +03:00
|
|
|
repo.ui.log(
|
|
|
|
"pinnednodes",
|
|
|
|
"pinnednodes: %r newpin=%r newunpin=%r " "before=%r after=%r\n",
|
|
|
|
fullargs,
|
|
|
|
desc(newpin),
|
|
|
|
desc(newunpin),
|
|
|
|
desc(orignodes),
|
|
|
|
desc(nodes),
|
|
|
|
)
|
|
|
|
|
2017-07-21 20:50:30 +03:00
|
|
|
|
2017-07-19 02:07:33 +03:00
|
|
|
def runcommand(orig, lui, repo, cmd, fullargs, *args):
|
2017-07-21 08:22:38 +03:00
|
|
|
# return directly for non-repo command
|
|
|
|
if not repo:
|
|
|
|
return orig(lui, repo, cmd, fullargs, *args)
|
|
|
|
|
|
|
|
shouldpinbefore = shouldpinnodes(repo) | set(loadpinnednodes(repo))
|
2017-07-19 02:07:33 +03:00
|
|
|
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
|
2018-05-30 12:16:33 +03:00
|
|
|
newunpin = getattr(repo.unfiltered(), "_tounpinnodes", set())
|
2017-07-21 08:22:38 +03:00
|
|
|
# filter newpin by obsolte - ex. if newpin is on a non-obsoleted commit,
|
|
|
|
# ignore it.
|
2017-09-26 23:34:34 +03:00
|
|
|
if newpin:
|
|
|
|
unfi = repo.unfiltered()
|
2018-05-30 12:16:33 +03:00
|
|
|
obsoleted = unfi.revs("obsolete()")
|
2017-09-26 23:34:34 +03:00
|
|
|
nodemap = unfi.changelog.nodemap
|
2018-05-30 12:16:33 +03:00
|
|
|
newpin = set(n for n in newpin if n in nodemap and nodemap[n] in obsoleted)
|
2017-07-19 02:07:33 +03:00
|
|
|
# only do a write if something has changed
|
|
|
|
if newpin or newunpin:
|
2017-07-21 20:50:30 +03:00
|
|
|
savepinnednodes(repo, newpin, newunpin, fullargs)
|
2017-07-13 21:04:56 +03:00
|
|
|
return result
|
|
|
|
|
2018-05-30 12:16:33 +03:00
|
|
|
|
2017-07-13 21:04:56 +03:00
|
|
|
def createmarkers(orig, repo, rels, *args, **kwargs):
|
|
|
|
# this is a way to unpin revs - precursors are unpinned
|
2017-07-21 08:22:38 +03:00
|
|
|
# note: hg debugobsolete does not call this function
|
2017-07-13 21:04:56 +03:00
|
|
|
unfi = repo.unfiltered()
|
2018-05-30 12:16:33 +03:00
|
|
|
tounpin = getattr(unfi, "_tounpinnodes", set())
|
2017-07-13 21:04:56 +03:00
|
|
|
for r in rels:
|
|
|
|
try:
|
|
|
|
tounpin.add(r[0].node())
|
|
|
|
except error.RepoLookupError:
|
|
|
|
pass
|
|
|
|
unfi._tounpinnodes = tounpin
|
|
|
|
return orig(repo, rels, *args, **kwargs)
|
2017-11-01 21:49:13 +03:00
|
|
|
|
2018-05-30 12:16:33 +03:00
|
|
|
|
2017-11-01 21:49:13 +03:00
|
|
|
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()
|
2018-05-30 12:16:33 +03:00
|
|
|
tounpin = getattr(unfi, "_tounpinnodes", set())
|
2017-11-01 21:49:13 +03:00
|
|
|
tounpin.update(mapping)
|
|
|
|
unfi._tounpinnodes = tounpin
|
|
|
|
return orig(repo, mapping, *args, **kwargs)
|