comparison 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
comparison
equal deleted inserted replaced
38706:83d965803325 38707:6b5ca1d0aa1e
72 import errno 72 import errno
73 import struct 73 import struct
74 74
75 from .i18n import _ 75 from .i18n import _
76 from . import ( 76 from . import (
77 encoding,
77 error, 78 error,
78 node, 79 node,
79 obsutil, 80 obsutil,
80 phases, 81 phases,
81 policy, 82 policy,
524 525
525 fields = ('prec', 'succs', 'flag', 'meta', 'date', 'parents') 526 fields = ('prec', 'succs', 'flag', 'meta', 'date', 'parents')
526 # prec: nodeid, predecessors changesets 527 # prec: nodeid, predecessors changesets
527 # succs: tuple of nodeid, successor changesets (0-N length) 528 # succs: tuple of nodeid, successor changesets (0-N length)
528 # flag: integer, flag field carrying modifier for the markers (see doc) 529 # flag: integer, flag field carrying modifier for the markers (see doc)
529 # meta: binary blob, encoded metadata dictionary 530 # meta: binary blob in UTF-8, encoded metadata dictionary
530 # date: (float, int) tuple, date of marker creation 531 # date: (float, int) tuple, date of marker creation
531 # parents: (tuple of nodeid) or None, parents of predecessors 532 # parents: (tuple of nodeid) or None, parents of predecessors
532 # None is used when no data has been recorded 533 # None is used when no data has been recorded
533 534
534 def __init__(self, svfs, defaultformat=_fm1version, readonly=False): 535 def __init__(self, svfs, defaultformat=_fm1version, readonly=False):
948 """Add obsolete markers between changesets in a repo 949 """Add obsolete markers between changesets in a repo
949 950
950 <relations> must be an iterable of (<old>, (<new>, ...)[,{metadata}]) 951 <relations> must be an iterable of (<old>, (<new>, ...)[,{metadata}])
951 tuple. `old` and `news` are changectx. metadata is an optional dictionary 952 tuple. `old` and `news` are changectx. metadata is an optional dictionary
952 containing metadata for this marker only. It is merged with the global 953 containing metadata for this marker only. It is merged with the global
953 metadata specified through the `metadata` argument of this function, 954 metadata specified through the `metadata` argument of this function.
955 Any string values in metadata must be UTF-8 bytes.
954 956
955 Trying to obsolete a public changeset will raise an exception. 957 Trying to obsolete a public changeset will raise an exception.
956 958
957 Current user and date are used except if specified otherwise in the 959 Current user and date are used except if specified otherwise in the
958 metadata attribute. 960 metadata attribute.
962 """ 964 """
963 # prepare metadata 965 # prepare metadata
964 if metadata is None: 966 if metadata is None:
965 metadata = {} 967 metadata = {}
966 if 'user' not in metadata: 968 if 'user' not in metadata:
967 develuser = repo.ui.config('devel', 'user.obsmarker') 969 luser = repo.ui.config('devel', 'user.obsmarker') or repo.ui.username()
968 if develuser: 970 metadata['user'] = encoding.fromlocal(luser)
969 metadata['user'] = develuser
970 else:
971 metadata['user'] = repo.ui.username()
972 971
973 # Operation metadata handling 972 # Operation metadata handling
974 useoperation = repo.ui.configbool('experimental', 973 useoperation = repo.ui.configbool('experimental',
975 'evolution.track-operation') 974 'evolution.track-operation')
976 if useoperation and operation: 975 if useoperation and operation: