diff --git a/contrib/xml.rnc b/contrib/xml.rnc
new file mode 100644
--- /dev/null
+++ b/contrib/xml.rnc
@@ -0,0 +1,41 @@
+# RelaxNG schema for "xml" log style
+# Inspired by Subversion's XML log format.
+
+start = log
+node.type = xsd:string {minLength = "40" maxLength = "40"}
+
+log = element log { logentry+ }
+logentry = element logentry {
+ logentry.attlist,
+ branch*, tag*, hgparent*,
+ author, date,
+ msg, paths?, copies?, extra*
+}
+logentry.attlist =
+ attribute revision {xsd:nonNegativeInteger}
+ & attribute node {node.type}
+branch = element branch { text }
+tag = element tag { text }
+hgparent = element parent {hgparent.attlist, text}
+hgparent.attlist =
+ attribute revision {xsd:integer {minInclusive = "-1"} }
+ & attribute node {node.type}
+author = element author { author.attlist, text }
+author.attlist =
+ attribute email {text}
+date = element date {xsd:dateTime}
+msg = element msg {msg.attlist, text}
+msg.attlist =
+ attribute xml:space {"preserve"}
+paths = element paths { path* }
+path = element path { path.attlist, text }
+path.attlist =
+ # Action: (A)dd, (M)odify, (R)emove
+ attribute action {"A"|"M"|"R"}
+copies = element copies { copy+ }
+copy = element copy { copy.attlist, text }
+copy.attlist =
+ attribute source {text}
+extra = element extra {extra.attlist, text}
+extra.attlist =
+ attribute key {text}
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -844,7 +844,7 @@ class changeset_templater(changeset_prin
self.ui.write(templater.stringify(self.t(key, **props)))
self.showpatch(ctx.node())
- if types['header']:
+ if types['footer']:
if not self.footer:
self.footer = templater.stringify(self.t(types['footer'],
**props))
diff --git a/mercurial/templates/map-cmdline.xml b/mercurial/templates/map-cmdline.xml
--- a/mercurial/templates/map-cmdline.xml
+++ b/mercurial/templates/map-cmdline.xml
@@ -3,6 +3,7 @@ footer = '\n'
changeset = '\n{branches}{tags}{parents}{author|person|xmlescape}\n{date|rfc3339date}\n{desc|xmlescape}\n\n'
changeset_verbose = '\n{branches}{tags}{parents}{author|person|xmlescape}\n{date|rfc3339date}\n{desc|xmlescape}\n\n{file_adds}{file_dels}{file_mods}\n{file_copies}\n'
+changeset_debug = '\n{branches}{tags}{parents}{author|person|xmlescape}\n{date|rfc3339date}\n{desc|xmlescape}\n\n{file_adds}{file_dels}{file_mods}\n{file_copies}{extras}\n'
file_add = '{file_add|xmlescape}\n'
file_mod = '{file_mod|xmlescape}\n'
@@ -15,3 +16,4 @@ end_file_copies = '\n'
parent = '\n'
branch = '{branch|xmlescape}\n'
tag = '{tag|xmlescape}\n'
+extra = '{value|xmlescape}\n'
diff --git a/mercurial/windows.py b/mercurial/windows.py
--- a/mercurial/windows.py
+++ b/mercurial/windows.py
@@ -203,7 +203,7 @@ def find_exe(command):
executable = findexisting(os.path.join(path, command))
if executable is not None:
return executable
- return None
+ return findexisting(os.path.expanduser(os.path.expandvars(command)))
def set_signal_handler():
try:
diff --git a/tests/test-command-template b/tests/test-command-template
--- a/tests/test-command-template
+++ b/tests/test-command-template
@@ -62,6 +62,14 @@ hg log --style compact
hg log -v --style compact
hg log --debug --style compact
+# Test xml styles
+echo '# xml style works (--style xml)'
+hg log --style xml
+echo '# xml style works (-v --style xml)'
+hg log -v --style xml
+echo '# xml style works (--debug --style xml)'
+hg log --debug --style xml
+
echo '# error if style not readable'
touch q
chmod 0 q
diff --git a/tests/test-command-template.out b/tests/test-command-template.out
--- a/tests/test-command-template.out
+++ b/tests/test-command-template.out
@@ -97,6 +97,266 @@ 0:-1,-1 1e4e1b8f71e0 1970-01-12 13:4
line 1
line 2
+# xml style works (--style xml)
+
+
+
+tip
+test
+2020-01-01T10:01:00+00:00
+third
+
+
+
+User Name
+1970-01-12T13:46:40+00:00
+second
+
+
+
+
+person
+1970-01-18T08:40:01+00:00
+merge
+
+
+
+person
+1970-01-18T08:40:00+00:00
+new head
+
+
+foo
+person
+1970-01-17T04:53:20+00:00
+new branch
+
+
+person
+1970-01-16T01:06:40+00:00
+no user, no domain
+
+
+other
+1970-01-14T21:20:00+00:00
+no person
+
+
+A. N. Other
+1970-01-13T17:33:20+00:00
+other 1
+other 2
+
+other 3
+
+
+User Name
+1970-01-12T13:46:40+00:00
+line 1
+line 2
+
+
+# xml style works (-v --style xml)
+
+
+
+tip
+test
+2020-01-01T10:01:00+00:00
+third
+
+fourth
+third
+second
+
+
+fourth
+
+
+
+
+User Name
+1970-01-12T13:46:40+00:00
+second
+
+second
+
+
+
+
+
+person
+1970-01-18T08:40:01+00:00
+merge
+
+
+
+
+
+person
+1970-01-18T08:40:00+00:00
+new head
+
+d
+
+
+
+foo
+person
+1970-01-17T04:53:20+00:00
+new branch
+
+
+
+
+person
+1970-01-16T01:06:40+00:00
+no user, no domain
+
+c
+
+
+
+other
+1970-01-14T21:20:00+00:00
+no person
+
+c
+
+
+
+A. N. Other
+1970-01-13T17:33:20+00:00
+other 1
+other 2
+
+other 3
+
+b
+
+
+
+User Name
+1970-01-12T13:46:40+00:00
+line 1
+line 2
+
+a
+
+
+
+# xml style works (--debug --style xml)
+
+
+
+tip
+
+
+test
+2020-01-01T10:01:00+00:00
+third
+
+fourth
+third
+second
+
+
+fourth
+
+default
+
+
+
+
+User Name
+1970-01-12T13:46:40+00:00
+second
+
+second
+
+default
+
+
+
+
+person
+1970-01-18T08:40:01+00:00
+merge
+
+
+default
+
+
+
+
+person
+1970-01-18T08:40:00+00:00
+new head
+
+d
+
+default
+
+
+foo
+
+
+person
+1970-01-17T04:53:20+00:00
+new branch
+
+
+foo
+
+
+
+
+person
+1970-01-16T01:06:40+00:00
+no user, no domain
+
+c
+
+default
+
+
+
+
+other
+1970-01-14T21:20:00+00:00
+no person
+
+c
+
+default
+
+
+
+
+A. N. Other
+1970-01-13T17:33:20+00:00
+other 1
+other 2
+
+other 3
+
+b
+
+default
+
+
+
+
+User Name
+1970-01-12T13:46:40+00:00
+line 1
+line 2
+
+a
+
+default
+
+
# error if style not readable
abort: Permission denied: ./q
# error if no style