From patchwork Tue Aug 25 19:56:41 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [5, of, 5] templater: heuristic to force header/footer in empty logs (issue4135) (BC) From: Matt Mackall X-Patchwork-Id: 10278 Message-Id: <2bc31865e766c9ca0847.1440532601@ruin.waste.org> To: mercurial-devel@selenic.com Date: Tue, 25 Aug 2015 14:56:41 -0500 # HG changeset patch # User Matt Mackall # 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. 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 + + + + $ hg log --style xml