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.
--- 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)