Patchwork [2,of,6] formatter: add helper to create a formatter optionally backed by file

mail settings
Submitter Yuya Nishihara
Date May 30, 2017, 4:07 p.m.
Message ID <3b1c26a047eb15f0d606.1496160430@mimosa>
Download mbox | patch
Permalink /patch/21069/
State Accepted
Headers show


Yuya Nishihara - May 30, 2017, 4:07 p.m.
# HG changeset patch
# User Yuya Nishihara <>
# Date 1495874418 -32400
#      Sat May 27 17:40:18 2017 +0900
# Node ID 3b1c26a047eb15f0d606ad6816a04cf83a0c9fc6
# Parent  933ca2eb5014dfdf99e9a55a72df7916c24d58ad
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 --git a/mercurial/ b/mercurial/
--- a/mercurial/
+++ b/mercurial/
@@ -103,6 +103,7 @@  baz: foo, bar
 from __future__ import absolute_import
+import contextlib
 import itertools
 import os
@@ -432,3 +433,29 @@  def formatter(ui, out, topic, opts):
     elif ui.configbool('ui', 'formatjson'):
         return jsonformatter(ui, out, topic, opts)
     return plainformatter(ui, out, topic, opts)
+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
+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)