pager: replace fout and ferr of all ui objects

Summary:
The `ui` object is a bit messy - there are repo specific ui, and non-repo ui,
and ui can be copied around.

This diff changes `fout` and `ferr` to an indirect type that can be mutated
globally so the streampager can affect the `fout` and `ferr` of all related `ui`
objects instead of just one single `ui`.

Reviewed By: DurhamG

Differential Revision: D20903568

fbshipit-source-id: b2f139b91a39c20c22261e03ce50f3cc59074291
This commit is contained in:
Jun Wu 2020-04-15 18:18:53 -07:00 committed by Facebook GitHub Bot
parent c2ffda7622
commit 4ea261914c
4 changed files with 44 additions and 13 deletions

View File

@ -73,6 +73,13 @@ class request(object):
self.repo = repo
# input/output/error streams
if fin and not isinstance(fin, util.refcell):
fin = util.refcell(fin)
if fout and not isinstance(fout, util.refcell):
fout = util.refcell(fout)
if ferr and not isinstance(ferr, util.refcell):
ferr = util.refcell(ferr)
self.fin = fin
self.fout = fout
self.ferr = ferr

View File

@ -204,9 +204,9 @@ class ui(object):
else:
self._uiconfig = uiconfig.uiconfig()
self.fout = util.stdout
self.ferr = util.stderr
self.fin = util.stdin
self.fout = util.refcell(util.stdout)
self.ferr = util.refcell(util.stderr)
self.fin = util.refcell(util.stdin)
self.pageractive = False
self._disablepager = False
self._tweaked = False
@ -825,8 +825,6 @@ class ui(object):
def _runinternalstreampager(self):
"""Start the builtin streampager"""
origfout = self.fout
origferr = self.ferr
origencoding = encoding.outputencoding
self.flush()
@ -850,15 +848,17 @@ class ui(object):
def close(self):
pass
self.fout = stream(pager.write)
self.ferr = stream(pager.write_err)
assert isinstance(self.fout, util.refcell)
assert isinstance(self.ferr, util.refcell)
origfout = self.fout.swap(stream(pager.write))
origferr = self.ferr.swap(stream(pager.write_err))
@self.atexit
def waitpager():
with self.timeblockedsection("pager"):
pager.close()
self.fout = origfout
self.ferr = origferr
self.fout.swap(origfout)
self.ferr.swap(origferr)
encoding.outputencoding = origencoding
self.pageractive = True

View File

@ -645,6 +645,34 @@ class transactional(pycompat.ABC):
self.release()
class refcell(object):
"""Similar to Rust's Rc<RefCell>. Shared *mutable* reference.
This is useful when object mutation needs to affect shared copies.
>>> a = refcell("abc")
>>> b = a
>>> a.swap("defg")
'abc'
>>> b.upper()
'DEFG'
"""
def __init__(self, obj):
self._obj = obj
def __getattr__(self, name):
return getattr(self._obj, name)
def __iter__(self):
return iter(self._obj)
def swap(self, obj):
origobj = self._obj
self._obj = obj
return origobj
@contextlib.contextmanager
def acceptintervention(tr=None):
"""A context manager that closes the transaction on InterventionRequired

View File

@ -1,9 +1,5 @@
#chg-compatible
#chg-compatible
#chg-compatible
#testcases v0 v1 v2
#if v0