Patchwork [5,of,5] templater: heuristic to force header/footer in empty logs (issue4135) (BC)

login
register
mail settings
Submitter Matt Mackall
Date Aug. 25, 2015, 7:56 p.m.
Message ID <2bc31865e766c9ca0847.1440532601@ruin.waste.org>
Download mbox | patch
Permalink /patch/10278/
State Accepted
Headers show

Comments

Matt Mackall - Aug. 25, 2015, 7:56 p.m.
# HG changeset patch
# User Matt Mackall <mpm@selenic.com>
# Date 1440528293 18000
#      Tue Aug 25 13:44:53 2015 -0500
# Node ID 2bc31865e766c9ca08472889a689dbf5e302d48e
# Parent  1b6f85c04ba5de786ea02badb8bd4bab81ac58bc
templater: heuristic to force header/footer in empty logs (issue4135) (BC)

This gets us a valid XML output with the xml style for empty logs.
Empty documents are not valid XML because they require a single root
element besides the optional header.

Prior to this change, there was no opportunity to print headers or
footers because their output was potentially dependent on the
changesets printed.

This heuristic will get into trouble if someone wants to use bare "{"
in a header.. which isn't that unreasonable.

Patch

diff -r 1b6f85c04ba5 -r 2bc31865e766 mercurial/cmdutil.py
--- a/mercurial/cmdutil.py	Tue Aug 25 13:38:20 2015 -0500
+++ b/mercurial/cmdutil.py	Tue Aug 25 13:44:53 2015 -0500
@@ -1431,6 +1431,30 @@ 
                 if mode and cur in self.t:
                     self._parts[t] = cur
 
+    def close(self):
+        # the commandline templater is problematic with headers vs footers:
+        # - headers are potentially variable based on changeset
+        # - duplicate headers are elided (eg for changelog style)
+        # - only the last computed footer is printed
+        # - with no csets, we printed nothing
+        # - this made our XML output invalid
+        #
+        # to fix this, we detect:
+        # - no header or footer calculated yet
+        # - constant header
+        # - constant footer
+        # (we can't print variable ones because we have no cset to supply)
+
+        if not self.lastheader and not self.footer:
+            self.footer = ""
+            h = self._parts['header']
+            if h and "{" not in self.t(h):
+                self.footer += templater.stringify(self.t(h))
+            f = self._parts['footer']
+            if f and "{" not in self.t(f):
+                self.footer += templater.stringify(self.t(f))
+        return super(changeset_templater, self).close()
+
     def _show(self, ctx, copies, matchfn, props):
         '''show a single changeset or file revision'''
 
diff -r 1b6f85c04ba5 -r 2bc31865e766 tests/test-command-template.t
--- a/tests/test-command-template.t	Tue Aug 25 13:38:20 2015 -0500
+++ b/tests/test-command-template.t	Tue Aug 25 13:44:53 2015 -0500
@@ -343,6 +343,11 @@ 
 
 Test xml styles:
 
+  $ hg log -r 'not all()' -Txml
+  <?xml version="1.0"?>
+  <log>
+  </log>
+
   $ hg log --style xml
   <?xml version="1.0"?>
   <log>