diff mercurial/obsolete.py @ 38707:6b5ca1d0aa1e

obsolete: store user name and note in UTF-8 (issue5754) (BC) Before, user names were stored in local encoding and transferred across repositories, which made it impossible to restore non-ASCII user names on different platforms. This patch fixes new markers to be encoded in UTF-8 and decoded back to local encoding when displaying. Existing markers are unfixable so they may result in mojibake. I don't like the API that requires metadata dict to be UTF-8 encoded, which is a source of bugs, but there's no abstraction layer to process the encoding thingy efficiently. So we apply the same rule as extras dict to obsstore metadata.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 15 Jul 2018 18:24:57 +0900
parents 02f992ac26e9
children ff1182d166a2
line wrap: on
line diff
--- a/mercurial/obsolete.py	Sun Jul 15 18:22:40 2018 +0900
+++ b/mercurial/obsolete.py	Sun Jul 15 18:24:57 2018 +0900
@@ -74,6 +74,7 @@
 
 from .i18n import _
 from . import (
+    encoding,
     error,
     node,
     obsutil,
@@ -526,7 +527,7 @@
     # prec:    nodeid, predecessors changesets
     # succs:   tuple of nodeid, successor changesets (0-N length)
     # flag:    integer, flag field carrying modifier for the markers (see doc)
-    # meta:    binary blob, encoded metadata dictionary
+    # meta:    binary blob in UTF-8, encoded metadata dictionary
     # date:    (float, int) tuple, date of marker creation
     # parents: (tuple of nodeid) or None, parents of predecessors
     #          None is used when no data has been recorded
@@ -950,7 +951,8 @@
     <relations> must be an iterable of (<old>, (<new>, ...)[,{metadata}])
     tuple. `old` and `news` are changectx. metadata is an optional dictionary
     containing metadata for this marker only. It is merged with the global
-    metadata specified through the `metadata` argument of this function,
+    metadata specified through the `metadata` argument of this function.
+    Any string values in metadata must be UTF-8 bytes.
 
     Trying to obsolete a public changeset will raise an exception.
 
@@ -964,11 +966,8 @@
     if metadata is None:
         metadata = {}
     if 'user' not in metadata:
-        develuser = repo.ui.config('devel', 'user.obsmarker')
-        if develuser:
-            metadata['user'] = develuser
-        else:
-            metadata['user'] = repo.ui.username()
+        luser = repo.ui.config('devel', 'user.obsmarker') or repo.ui.username()
+        metadata['user'] = encoding.fromlocal(luser)
 
     # Operation metadata handling
     useoperation = repo.ui.configbool('experimental',