diff hgext/convert/cvsps.py @ 33388:0823f0983eaa

convert: transcode CVS log messages by specified encoding (issue5597) Converting from CVS to Mercurial assumes that CVS log messages in "cvs rlog" output are encoded in UTF-8 (or basic Latin-1). But cvs itself is usually unaware of encoding of log messages, in practice. Therefore, if there are commits, of which log message is encoded in other than UTF-8, log message of corresponded revisions in the converted repository will be broken. To avoid such broken log messages, this patch transcodes CVS log messages by encoding specified via "convert.cvsps.logencoding" configuration. This patch accepts multiple encoding for convenience, because "multiple encoding mixed in a repository" easily occurs. For example, UTF-8 (recent POSIX), cp932 (Windows), and EUC-JP (legacy POSIX) are well known encoding for Japanese.
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Tue, 11 Jul 2017 02:10:04 +0900
parents 6e3c79bc9a35
children 0fa781320203
line wrap: on
line diff
--- a/hgext/convert/cvsps.py	Mon Jul 10 23:09:52 2017 +0900
+++ b/hgext/convert/cvsps.py	Tue Jul 11 02:10:04 2017 +0900
@@ -12,6 +12,7 @@
 from mercurial.i18n import _
 from mercurial import (
     encoding,
+    error,
     hook,
     pycompat,
     util,
@@ -491,6 +492,35 @@
 
     ui.status(_('%d log entries\n') % len(log))
 
+    encodings = ui.configlist('convert', 'cvsps.logencoding')
+    if encodings:
+        def revstr(r):
+            # this is needed, because logentry.revision is a tuple of "int"
+            # (e.g. (1, 2) for "1.2")
+            return '.'.join(pycompat.maplist(pycompat.bytestr, r))
+
+        for entry in log:
+            comment = entry.comment
+            for e in encodings:
+                try:
+                    entry.comment = comment.decode(e).encode('utf-8')
+                    if ui.debugflag:
+                        ui.debug("transcoding by %s: %s of %s\n" %
+                                 (e, revstr(entry.revision), entry.file))
+                    break
+                except UnicodeDecodeError:
+                    pass # try next encoding
+                except LookupError as inst: # unknown encoding, maybe
+                    raise error.Abort(inst,
+                                      hint=_('check convert.cvsps.logencoding'
+                                             ' configuration'))
+            else:
+                raise error.Abort(_("no encoding can transcode"
+                                    " CVS log message for %s of %s")
+                                  % (revstr(entry.revision), entry.file),
+                                  hint=_('check convert.cvsps.logencoding'
+                                         ' configuration'))
+
     hook.hook(ui, None, "cvslog", True, log=log)
 
     return log