# HG changeset patch # User Yuya Nishihara # Date 1495874418 -32400 # Node ID 35985d407d49c03fb54740f17d261f2d536ba655 # Parent 012e0da5b75914f0136c5aea869a981785f34a66 formatter: add helper to create a formatter optionally backed by file To make things simple, openformatter() and maybereopen() have no support for a plain object API. Callers must use the "with" statement. Unlike cmdutil.makefileobj(), append mode ('ab') isn't supported by these functions. This is because JSON output can't be simply concatenated. Perhaps cmdutil.export() will have to build a {filename: [revs...]} map first and write revs per file. diff -r 012e0da5b759 -r 35985d407d49 mercurial/formatter.py --- a/mercurial/formatter.py Sun Jan 18 18:04:44 2015 +0900 +++ b/mercurial/formatter.py Sat May 27 17:40:18 2017 +0900 @@ -103,6 +103,7 @@ from __future__ import absolute_import +import contextlib import itertools import os @@ -432,3 +433,29 @@ elif ui.configbool('ui', 'formatjson'): return jsonformatter(ui, out, topic, opts) return plainformatter(ui, out, topic, opts) + +@contextlib.contextmanager +def openformatter(ui, filename, topic, opts): + """Create a formatter that writes outputs to the specified file + + Must be invoked using the 'with' statement. + """ + with util.posixfile(filename, 'wb') as out: + with formatter(ui, out, topic, opts) as fm: + yield fm + +@contextlib.contextmanager +def _neverending(fm): + yield fm + +def maybereopen(fm, filename, opts): + """Create a formatter backed by file if filename specified, else return + the given formatter + + Must be invoked using the 'with' statement. This will never call fm.end() + of the given formatter. + """ + if filename: + return openformatter(fm._ui, filename, fm._topic, opts) + else: + return _neverending(fm)