diff mercurial/ui.py @ 43077:687b865b95ad

formatting: byteify all mercurial/ and hgext/ string literals Done with python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py') black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**') # skip-blame mass-reformatting only Differential Revision: https://phab.mercurial-scm.org/D6972
author Augie Fackler <augie@google.com>
date Sun, 06 Oct 2019 09:48:39 -0400
parents 2372284d9457
children 5209fc94b982
line wrap: on
line diff
--- a/mercurial/ui.py	Sun Oct 06 09:45:02 2019 -0400
+++ b/mercurial/ui.py	Sun Oct 06 09:48:39 2019 -0400
@@ -46,7 +46,7 @@
 urlreq = util.urlreq
 
 # for use with str.translate(None, _keepalnum), to keep just alphanumerics
-_keepalnum = ''.join(
+_keepalnum = b''.join(
     c for c in map(pycompat.bytechr, range(256)) if not c.isalnum()
 )
 
@@ -79,7 +79,7 @@
 """
 
 samplehgrcs = {
-    'user': b"""# example user config (see 'hg help config' for more info)
+    b'user': b"""# example user config (see 'hg help config' for more info)
 [ui]
 # name and email, e.g.
 # username = Jane Doe <jdoe@example.com>
@@ -106,7 +106,7 @@
 # rebase =
 # uncommit =
 """,
-    'cloned': b"""# example repository config (see 'hg help config' for more info)
+    b'cloned': b"""# example repository config (see 'hg help config' for more info)
 [paths]
 default = %s
 
@@ -121,7 +121,7 @@
 # name and email (local to this repository, optional), e.g.
 # username = Jane Doe <jdoe@example.com>
 """,
-    'local': b"""# example repository config (see 'hg help config' for more info)
+    b'local': b"""# example repository config (see 'hg help config' for more info)
 [paths]
 # path aliases to other clones of this repo in URLs or filesystem paths
 # (see 'hg help config.paths' for more info)
@@ -135,7 +135,7 @@
 # name and email (local to this repository, optional), e.g.
 # username = Jane Doe <jdoe@example.com>
 """,
-    'global': b"""# example system-wide hg config (see 'hg help config' for more info)
+    b'global': b"""# example system-wide hg config (see 'hg help config' for more info)
 
 [ui]
 # uncomment to disable color in command output
@@ -285,8 +285,8 @@
             self.httppasswordmgrdb = httppasswordmgrdbproxy()
             self._blockedtimes = collections.defaultdict(int)
 
-        allowed = self.configlist('experimental', 'exportableenviron')
-        if '*' in allowed:
+        allowed = self.configlist(b'experimental', b'exportableenviron')
+        if b'*' in allowed:
             self._exportableenviron = self.environ
         else:
             self._exportableenviron = {}
@@ -300,9 +300,9 @@
         u = cls()
         # we always trust global config files and environment variables
         for t, f in rcutil.rccomponents():
-            if t == 'path':
+            if t == b'path':
                 u.readconfig(f, trust=True)
-            elif t == 'items':
+            elif t == b'items':
                 sections = set()
                 for section, name, value, source in f:
                     # do not set u._ocfg
@@ -313,14 +313,14 @@
                 for section in sections:
                     u.fixconfig(section=section)
             else:
-                raise error.ProgrammingError('unknown rctype: %s' % t)
+                raise error.ProgrammingError(b'unknown rctype: %s' % t)
         u._maybetweakdefaults()
         return u
 
     def _maybetweakdefaults(self):
-        if not self.configbool('ui', 'tweakdefaults'):
+        if not self.configbool(b'ui', b'tweakdefaults'):
             return
-        if self._tweaked or self.plain('tweakdefaults'):
+        if self._tweaked or self.plain(b'tweakdefaults'):
             return
 
         # Note: it is SUPER IMPORTANT that you set self._tweaked to
@@ -331,11 +331,11 @@
         # avoid this weirdness.
         self._tweaked = True
         tmpcfg = config.config()
-        tmpcfg.parse('<tweakdefaults>', tweakrc)
+        tmpcfg.parse(b'<tweakdefaults>', tweakrc)
         for section in tmpcfg:
             for name, value in tmpcfg.items(section):
                 if not self.hasconfig(section, name):
-                    self.setconfig(section, name, value, "<tweakdefaults>")
+                    self.setconfig(section, name, value, b"<tweakdefaults>")
 
     def copy(self):
         return self.__class__(self)
@@ -353,7 +353,7 @@
         try:
             yield
         finally:
-            self._blockedtimes[key + '_blocked'] += (
+            self._blockedtimes[key + b'_blocked'] += (
                 util.timer() - starttime
             ) * 1000
 
@@ -366,9 +366,9 @@
         lets you advise Mercurial that something risky is happening so
         that control-C etc can be blocked if desired.
         """
-        enabled = self.configbool('experimental', 'nointerrupt')
+        enabled = self.configbool(b'experimental', b'nointerrupt')
         if enabled and self.configbool(
-            'experimental', 'nointerrupt-interactiveonly'
+            b'experimental', b'nointerrupt-interactiveonly'
         ):
             enabled = self.interactive()
         if self._uninterruptible or not enabled:
@@ -379,9 +379,9 @@
             return
 
         def warn():
-            self.warn(_("shutting down cleanly\n"))
+            self.warn(_(b"shutting down cleanly\n"))
             self.warn(
-                _("press ^C again to terminate immediately (dangerous)\n")
+                _(b"press ^C again to terminate immediately (dangerous)\n")
             )
             return True
 
@@ -401,7 +401,7 @@
             return True
 
         tusers, tgroups = self._trustusers, self._trustgroups
-        if '*' in tusers or '*' in tgroups:
+        if b'*' in tusers or b'*' in tgroups:
             return True
 
         user = util.username(st.st_uid)
@@ -411,7 +411,10 @@
 
         if self._reportuntrusted:
             self.warn(
-                _('not trusting file %s from untrusted ' 'user %s, group %s\n')
+                _(
+                    b'not trusting file %s from untrusted '
+                    b'user %s, group %s\n'
+                )
                 % (f, user, group)
             )
         return False
@@ -435,37 +438,37 @@
         except error.ConfigError as inst:
             if trusted:
                 raise
-            self.warn(_("ignored: %s\n") % stringutil.forcebytestr(inst))
+            self.warn(_(b"ignored: %s\n") % stringutil.forcebytestr(inst))
 
         if self.plain():
             for k in (
-                'debug',
-                'fallbackencoding',
-                'quiet',
-                'slash',
-                'logtemplate',
-                'message-output',
-                'statuscopies',
-                'style',
-                'traceback',
-                'verbose',
+                b'debug',
+                b'fallbackencoding',
+                b'quiet',
+                b'slash',
+                b'logtemplate',
+                b'message-output',
+                b'statuscopies',
+                b'style',
+                b'traceback',
+                b'verbose',
             ):
-                if k in cfg['ui']:
-                    del cfg['ui'][k]
-            for k, v in cfg.items('defaults'):
-                del cfg['defaults'][k]
-            for k, v in cfg.items('commands'):
-                del cfg['commands'][k]
+                if k in cfg[b'ui']:
+                    del cfg[b'ui'][k]
+            for k, v in cfg.items(b'defaults'):
+                del cfg[b'defaults'][k]
+            for k, v in cfg.items(b'commands'):
+                del cfg[b'commands'][k]
         # Don't remove aliases from the configuration if in the exceptionlist
-        if self.plain('alias'):
-            for k, v in cfg.items('alias'):
-                del cfg['alias'][k]
-        if self.plain('revsetalias'):
-            for k, v in cfg.items('revsetalias'):
-                del cfg['revsetalias'][k]
-        if self.plain('templatealias'):
-            for k, v in cfg.items('templatealias'):
-                del cfg['templatealias'][k]
+        if self.plain(b'alias'):
+            for k, v in cfg.items(b'alias'):
+                del cfg[b'alias'][k]
+        if self.plain(b'revsetalias'):
+            for k, v in cfg.items(b'revsetalias'):
+                del cfg[b'revsetalias'][k]
+        if self.plain(b'templatealias'):
+            for k, v in cfg.items(b'templatealias'):
+                del cfg[b'templatealias'][k]
 
         if trusted:
             self._tcfg.update(cfg)
@@ -474,51 +477,51 @@
         self._ucfg.update(self._ocfg)
 
         if root is None:
-            root = os.path.expanduser('~')
+            root = os.path.expanduser(b'~')
         self.fixconfig(root=root)
 
     def fixconfig(self, root=None, section=None):
-        if section in (None, 'paths'):
+        if section in (None, b'paths'):
             # expand vars and ~
             # translate paths relative to root (or home) into absolute paths
             root = root or encoding.getcwd()
             for c in self._tcfg, self._ucfg, self._ocfg:
-                for n, p in c.items('paths'):
+                for n, p in c.items(b'paths'):
                     # Ignore sub-options.
-                    if ':' in n:
+                    if b':' in n:
                         continue
                     if not p:
                         continue
-                    if '%%' in p:
-                        s = self.configsource('paths', n) or 'none'
+                    if b'%%' in p:
+                        s = self.configsource(b'paths', n) or b'none'
                         self.warn(
-                            _("(deprecated '%%' in path %s=%s from %s)\n")
+                            _(b"(deprecated '%%' in path %s=%s from %s)\n")
                             % (n, p, s)
                         )
-                        p = p.replace('%%', '%')
+                        p = p.replace(b'%%', b'%')
                     p = util.expandpath(p)
                     if not util.hasscheme(p) and not os.path.isabs(p):
                         p = os.path.normpath(os.path.join(root, p))
-                    c.set("paths", n, p)
+                    c.set(b"paths", n, p)
 
-        if section in (None, 'ui'):
+        if section in (None, b'ui'):
             # update ui options
             self._fmsgout, self._fmsgerr = _selectmsgdests(self)
-            self.debugflag = self.configbool('ui', 'debug')
-            self.verbose = self.debugflag or self.configbool('ui', 'verbose')
-            self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
+            self.debugflag = self.configbool(b'ui', b'debug')
+            self.verbose = self.debugflag or self.configbool(b'ui', b'verbose')
+            self.quiet = not self.debugflag and self.configbool(b'ui', b'quiet')
             if self.verbose and self.quiet:
                 self.quiet = self.verbose = False
             self._reportuntrusted = self.debugflag or self.configbool(
-                "ui", "report_untrusted"
+                b"ui", b"report_untrusted"
             )
-            self.tracebackflag = self.configbool('ui', 'traceback')
-            self.logblockedtimes = self.configbool('ui', 'logblockedtimes')
+            self.tracebackflag = self.configbool(b'ui', b'traceback')
+            self.logblockedtimes = self.configbool(b'ui', b'logblockedtimes')
 
-        if section in (None, 'trusted'):
+        if section in (None, b'trusted'):
             # update trust information
-            self._trustusers.update(self.configlist('trusted', 'users'))
-            self._trustgroups.update(self.configlist('trusted', 'groups'))
+            self._trustusers.update(self.configlist(b'trusted', b'users'))
+            self._trustgroups.update(self.configlist(b'trusted', b'groups'))
 
         if section in (None, b'devel', b'ui') and self.debugflag:
             tracked = set()
@@ -540,7 +543,7 @@
         self._tcfg.restore(data[1])
         self._ucfg.restore(data[2])
 
-    def setconfig(self, section, name, value, source=''):
+    def setconfig(self, section, name, value, source=b''):
         for cfg in (self._ocfg, self._tcfg, self._ucfg):
             cfg.set(section, name, value, source)
         self.fixconfig(section=section)
@@ -573,18 +576,18 @@
             else:
                 itemdefault = item.default
         else:
-            msg = "accessing unregistered config item: '%s.%s'"
+            msg = b"accessing unregistered config item: '%s.%s'"
             msg %= (section, name)
-            self.develwarn(msg, 2, 'warn-config-unknown')
+            self.develwarn(msg, 2, b'warn-config-unknown')
 
         if default is _unset:
             if item is None:
                 value = default
             elif item.default is configitems.dynamicdefault:
                 value = None
-                msg = "config item requires an explicit default value: '%s.%s'"
+                msg = b"config item requires an explicit default value: '%s.%s'"
                 msg %= (section, name)
-                self.develwarn(msg, 2, 'warn-config-default')
+                self.develwarn(msg, 2, b'warn-config-default')
             else:
                 value = itemdefault
         elif (
@@ -593,11 +596,11 @@
             and default != itemdefault
         ):
             msg = (
-                "specifying a mismatched default value for a registered "
-                "config item: '%s.%s' '%s'"
+                b"specifying a mismatched default value for a registered "
+                b"config item: '%s.%s' '%s'"
             )
             msg %= (section, name, pycompat.bytestr(default))
-            self.develwarn(msg, 2, 'warn-config-default')
+            self.develwarn(msg, 2, b'warn-config-default')
 
         for s, n in alternates:
             candidate = self._data(untrusted).get(s, n, None)
@@ -610,8 +613,8 @@
                 uvalue = self._ucfg.get(s, n)
                 if uvalue is not None and uvalue != value:
                     self.debug(
-                        "ignoring untrusted configuration option "
-                        "%s.%s = %s\n" % (s, n, uvalue)
+                        b"ignoring untrusted configuration option "
+                        b"%s.%s = %s\n" % (s, n, uvalue)
                     )
         return value
 
@@ -628,31 +631,31 @@
         main = self.config(section, name, default, untrusted=untrusted)
         data = self._data(untrusted)
         sub = {}
-        prefix = '%s:' % name
+        prefix = b'%s:' % name
         for k, v in data.items(section):
             if k.startswith(prefix):
                 sub[k[len(prefix) :]] = v
 
         if self.debugflag and not untrusted and self._reportuntrusted:
             for k, v in sub.items():
-                uvalue = self._ucfg.get(section, '%s:%s' % (name, k))
+                uvalue = self._ucfg.get(section, b'%s:%s' % (name, k))
                 if uvalue is not None and uvalue != v:
                     self.debug(
-                        'ignoring untrusted configuration option '
-                        '%s:%s.%s = %s\n' % (section, name, k, uvalue)
+                        b'ignoring untrusted configuration option '
+                        b'%s:%s.%s = %s\n' % (section, name, k, uvalue)
                     )
 
         return main, sub
 
     def configpath(self, section, name, default=_unset, untrusted=False):
-        'get a path config item, expanded relative to repo root or config file'
+        b'get a path config item, expanded relative to repo root or config file'
         v = self.config(section, name, default, untrusted)
         if v is None:
             return None
-        if not os.path.isabs(v) or "://" not in v:
+        if not os.path.isabs(v) or b"://" not in v:
             src = self.configsource(section, name, untrusted)
-            if ':' in src:
-                base = os.path.dirname(src.rsplit(':')[0])
+            if b':' in src:
+                base = os.path.dirname(src.rsplit(b':')[0])
                 v = os.path.join(base, os.path.expanduser(v))
         return v
 
@@ -689,7 +692,7 @@
         b = stringutil.parsebool(v)
         if b is None:
             raise error.ConfigError(
-                _("%s.%s is not a boolean ('%s')") % (section, name, v)
+                _(b"%s.%s is not a boolean ('%s')") % (section, name, v)
             )
         return b
 
@@ -727,7 +730,7 @@
             if desc is None:
                 desc = pycompat.sysbytes(convert.__name__)
             raise error.ConfigError(
-                _("%s.%s is not a valid %s ('%s')") % (section, name, desc, v)
+                _(b"%s.%s is not a valid %s ('%s')") % (section, name, desc, v)
             )
 
     def configint(self, section, name, default=_unset, untrusted=False):
@@ -750,7 +753,7 @@
         """
 
         return self.configwith(
-            int, section, name, default, 'integer', untrusted
+            int, section, name, default, b'integer', untrusted
         )
 
     def configbytes(self, section, name, default=_unset, untrusted=False):
@@ -786,7 +789,7 @@
             return util.sizetoint(value)
         except error.ParseError:
             raise error.ConfigError(
-                _("%s.%s is not a byte quantity ('%s')")
+                _(b"%s.%s is not a byte quantity ('%s')")
                 % (section, name, value)
             )
 
@@ -804,7 +807,7 @@
         """
         # default is not always a list
         v = self.configwith(
-            config.parselist, section, name, default, 'list', untrusted
+            config.parselist, section, name, default, b'list', untrusted
         )
         if isinstance(v, bytes):
             return config.parselist(v)
@@ -822,7 +825,7 @@
         """
         if self.config(section, name, default, untrusted):
             return self.configwith(
-                dateutil.parsedate, section, name, default, 'date', untrusted
+                dateutil.parsedate, section, name, default, b'date', untrusted
             )
         if default is _unset:
             return None
@@ -849,13 +852,13 @@
     def configitems(self, section, untrusted=False, ignoresub=False):
         items = self._data(untrusted).items(section)
         if ignoresub:
-            items = [i for i in items if ':' not in i[0]]
+            items = [i for i in items if b':' not in i[0]]
         if self.debugflag and not untrusted and self._reportuntrusted:
             for k, v in self._ucfg.items(section):
                 if self._tcfg.get(section, k) != v:
                     self.debug(
-                        "ignoring untrusted configuration option "
-                        "%s.%s = %s\n" % (section, k, v)
+                        b"ignoring untrusted configuration option "
+                        b"%s.%s = %s\n" % (section, k, v)
                     )
         return items
 
@@ -882,16 +885,18 @@
         - True otherwise
         '''
         if (
-            'HGPLAIN' not in encoding.environ
-            and 'HGPLAINEXCEPT' not in encoding.environ
+            b'HGPLAIN' not in encoding.environ
+            and b'HGPLAINEXCEPT' not in encoding.environ
         ):
             return False
         exceptions = (
-            encoding.environ.get('HGPLAINEXCEPT', '').strip().split(',')
+            encoding.environ.get(b'HGPLAINEXCEPT', b'').strip().split(b',')
         )
         # TODO: add support for HGPLAIN=+feature,-feature syntax
-        if '+strictflags' not in encoding.environ.get('HGPLAIN', '').split(','):
-            exceptions.append('strictflags')
+        if b'+strictflags' not in encoding.environ.get(b'HGPLAIN', b'').split(
+            b','
+        ):
+            exceptions.append(b'strictflags')
         if feature and exceptions:
             return feature not in exceptions
         return True
@@ -906,34 +911,34 @@
         ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
         If no username could be found, raise an Abort error.
         """
-        user = encoding.environ.get("HGUSER")
+        user = encoding.environ.get(b"HGUSER")
         if user is None:
-            user = self.config("ui", "username")
+            user = self.config(b"ui", b"username")
             if user is not None:
                 user = os.path.expandvars(user)
         if user is None:
-            user = encoding.environ.get("EMAIL")
+            user = encoding.environ.get(b"EMAIL")
         if user is None and acceptempty:
             return user
-        if user is None and self.configbool("ui", "askusername"):
-            user = self.prompt(_("enter a commit username:"), default=None)
+        if user is None and self.configbool(b"ui", b"askusername"):
+            user = self.prompt(_(b"enter a commit username:"), default=None)
         if user is None and not self.interactive():
             try:
-                user = '%s@%s' % (
+                user = b'%s@%s' % (
                     procutil.getuser(),
                     encoding.strtolocal(socket.getfqdn()),
                 )
-                self.warn(_("no username found, using '%s' instead\n") % user)
+                self.warn(_(b"no username found, using '%s' instead\n") % user)
             except KeyError:
                 pass
         if not user:
             raise error.Abort(
-                _('no username supplied'),
-                hint=_("use 'hg config --edit' " 'to set your username'),
+                _(b'no username supplied'),
+                hint=_(b"use 'hg config --edit' " b'to set your username'),
             )
-        if "\n" in user:
+        if b"\n" in user:
             raise error.Abort(
-                _("username %r contains a newline\n") % pycompat.bytestr(user)
+                _(b"username %r contains a newline\n") % pycompat.bytestr(user)
             )
         return user
 
@@ -1030,7 +1035,7 @@
         else:
             self._bufferapplylabels = None
 
-        return "".join(self._buffers.pop())
+        return b"".join(self._buffers.pop())
 
     def _isbuffered(self, dest):
         if dest is self._fout:
@@ -1048,7 +1053,7 @@
     def canbatchlabeledwrites(self):
         '''check if write calls with labels are batchable'''
         # Windows color printing is special, see ``write``.
-        return self._colormode != 'win32'
+        return self._colormode != b'win32'
 
     def write(self, *args, **opts):
         '''write args to output
@@ -1070,7 +1075,7 @@
 
         # inlined _write() for speed
         if self._buffers:
-            label = opts.get(r'label', '')
+            label = opts.get(r'label', b'')
             if label and self._bufferapplylabels:
                 self._buffers[-1].extend(self.label(a, label) for a in args)
             else:
@@ -1084,19 +1089,19 @@
         # opencode timeblockedsection because this is a critical path
         starttime = util.timer()
         try:
-            if self._colormode == 'win32':
+            if self._colormode == b'win32':
                 # windows color printing is its own can of crab, defer to
                 # the color module and that is it.
                 color.win32print(self, dest.write, msg, **opts)
             else:
                 if self._colormode is not None:
-                    label = opts.get(r'label', '')
+                    label = opts.get(r'label', b'')
                     msg = self.label(msg, label)
                 dest.write(msg)
         except IOError as err:
             raise error.StdioError(err)
         finally:
-            self._blockedtimes['stdio_blocked'] += (
+            self._blockedtimes[b'stdio_blocked'] += (
                 util.timer() - starttime
             ) * 1000
 
@@ -1106,7 +1111,7 @@
     def _write(self, dest, *args, **opts):
         # update write() as well if you touch this code
         if self._isbuffered(dest):
-            label = opts.get(r'label', '')
+            label = opts.get(r'label', b'')
             if label and self._bufferapplylabels:
                 self._buffers[-1].extend(self.label(a, label) for a in args)
             else:
@@ -1128,13 +1133,13 @@
                 # channel for machine-readable output with metadata, where
                 # no extra colorization is necessary.
                 dest.write(msg, **opts)
-            elif self._colormode == 'win32':
+            elif self._colormode == b'win32':
                 # windows color printing is its own can of crab, defer to
                 # the color module and that is it.
                 color.win32print(self, dest.write, msg, **opts)
             else:
                 if self._colormode is not None:
-                    label = opts.get(r'label', '')
+                    label = opts.get(r'label', b'')
                     msg = self.label(msg, label)
                 dest.write(msg)
             # stderr may be buffered under win32 when redirected to files,
@@ -1151,7 +1156,7 @@
                 return
             raise error.StdioError(err)
         finally:
-            self._blockedtimes['stdio_blocked'] += (
+            self._blockedtimes[b'stdio_blocked'] += (
                 util.timer() - starttime
             ) * 1000
 
@@ -1177,12 +1182,12 @@
                     if err.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
                         raise error.StdioError(err)
         finally:
-            self._blockedtimes['stdio_blocked'] += (
+            self._blockedtimes[b'stdio_blocked'] += (
                 util.timer() - starttime
             ) * 1000
 
     def _isatty(self, fh):
-        if self.configbool('ui', 'nontty'):
+        if self.configbool(b'ui', b'nontty'):
             return False
         return procutil.isatty(fh)
 
@@ -1239,27 +1244,27 @@
             # how pager should do is already determined
             return
 
-        if not command.startswith('internal-always-') and (
+        if not command.startswith(b'internal-always-') and (
             # explicit --pager=on (= 'internal-always-' prefix) should
             # take precedence over disabling factors below
-            command in self.configlist('pager', 'ignore')
-            or not self.configbool('ui', 'paginate')
-            or not self.configbool('pager', 'attend-' + command, True)
-            or encoding.environ.get('TERM') == 'dumb'
+            command in self.configlist(b'pager', b'ignore')
+            or not self.configbool(b'ui', b'paginate')
+            or not self.configbool(b'pager', b'attend-' + command, True)
+            or encoding.environ.get(b'TERM') == b'dumb'
             # TODO: if we want to allow HGPLAINEXCEPT=pager,
             # formatted() will need some adjustment.
             or not self.formatted()
             or self.plain()
             or self._buffers
             # TODO: expose debugger-enabled on the UI object
-            or '--debugger' in pycompat.sysargv
+            or b'--debugger' in pycompat.sysargv
         ):
             # We only want to paginate if the ui appears to be
             # interactive, the user didn't say HGPLAIN or
             # HGPLAINEXCEPT=pager, and the user didn't specify --debug.
             return
 
-        pagercmd = self.config('pager', 'pager', rcutil.fallbackpager)
+        pagercmd = self.config(b'pager', b'pager', rcutil.fallbackpager)
         if not pagercmd:
             return
 
@@ -1269,25 +1274,25 @@
                 pagerenv[name] = value
 
         self.debug(
-            'starting pager for command %s\n' % stringutil.pprint(command)
+            b'starting pager for command %s\n' % stringutil.pprint(command)
         )
         self.flush()
 
         wasformatted = self.formatted()
-        if util.safehasattr(signal, "SIGPIPE"):
+        if util.safehasattr(signal, b"SIGPIPE"):
             signal.signal(signal.SIGPIPE, _catchterm)
         if self._runpager(pagercmd, pagerenv):
             self.pageractive = True
             # Preserve the formatted-ness of the UI. This is important
             # because we mess with stdout, which might confuse
             # auto-detection of things being formatted.
-            self.setconfig('ui', 'formatted', wasformatted, 'pager')
-            self.setconfig('ui', 'interactive', False, 'pager')
+            self.setconfig(b'ui', b'formatted', wasformatted, b'pager')
+            self.setconfig(b'ui', b'interactive', False, b'pager')
 
             # If pagermode differs from color.mode, reconfigure color now that
             # pageractive is set.
             cm = self._colormode
-            if cm != self.config('color', 'pagermode', cm):
+            if cm != self.config(b'color', b'pagermode', cm):
                 color.setup(self)
         else:
             # If the pager can't be spawned in dispatch when --pager=on is
@@ -1301,14 +1306,14 @@
         This is separate in part so that extensions (like chg) can
         override how a pager is invoked.
         """
-        if command == 'cat':
+        if command == b'cat':
             # Save ourselves some work.
             return False
         # If the command doesn't contain any of these characters, we
         # assume it's a binary and exec it directly. This means for
         # simple pager command configurations, we can degrade
         # gracefully and tell the user about their broken pager.
-        shell = any(c in command for c in "|&;<>()$`\\\"' \t\n*?[#~=%")
+        shell = any(c in command for c in b"|&;<>()$`\\\"' \t\n*?[#~=%")
 
         if pycompat.iswindows and not shell:
             # Window's built-in `more` cannot be invoked with shell=False, but
@@ -1319,7 +1324,7 @@
             fullcmd = procutil.findexe(command)
             if not fullcmd:
                 self.warn(
-                    _("missing pager command '%s', skipping pager\n") % command
+                    _(b"missing pager command '%s', skipping pager\n") % command
                 )
                 return False
 
@@ -1339,7 +1344,7 @@
         except OSError as e:
             if e.errno == errno.ENOENT and not shell:
                 self.warn(
-                    _("missing pager command '%s', skipping pager\n") % command
+                    _(b"missing pager command '%s', skipping pager\n") % command
                 )
                 return False
             raise
@@ -1354,7 +1359,7 @@
 
         @self.atexit
         def killpager():
-            if util.safehasattr(signal, "SIGINT"):
+            if util.safehasattr(signal, b"SIGINT"):
                 signal.signal(signal.SIGINT, signal.SIG_IGN)
             # restore original fds, closing pager.stdin copies in the process
             os.dup2(stdoutfd, procutil.stdout.fileno())
@@ -1397,51 +1402,51 @@
         Then histedit will use the text interface and chunkselector will use
         the default curses interface (crecord at the moment).
         """
-        alldefaults = frozenset(["text", "curses"])
+        alldefaults = frozenset([b"text", b"curses"])
 
         featureinterfaces = {
-            "chunkselector": ["text", "curses",],
-            "histedit": ["text", "curses",],
+            b"chunkselector": [b"text", b"curses",],
+            b"histedit": [b"text", b"curses",],
         }
 
         # Feature-specific interface
         if feature not in featureinterfaces.keys():
             # Programming error, not user error
-            raise ValueError("Unknown feature requested %s" % feature)
+            raise ValueError(b"Unknown feature requested %s" % feature)
 
         availableinterfaces = frozenset(featureinterfaces[feature])
         if alldefaults > availableinterfaces:
             # Programming error, not user error. We need a use case to
             # define the right thing to do here.
             raise ValueError(
-                "Feature %s does not handle all default interfaces" % feature
+                b"Feature %s does not handle all default interfaces" % feature
             )
 
-        if self.plain() or encoding.environ.get('TERM') == 'dumb':
-            return "text"
+        if self.plain() or encoding.environ.get(b'TERM') == b'dumb':
+            return b"text"
 
         # Default interface for all the features
-        defaultinterface = "text"
-        i = self.config("ui", "interface")
+        defaultinterface = b"text"
+        i = self.config(b"ui", b"interface")
         if i in alldefaults:
             defaultinterface = i
 
         choseninterface = defaultinterface
-        f = self.config("ui", "interface.%s" % feature)
+        f = self.config(b"ui", b"interface.%s" % feature)
         if f in availableinterfaces:
             choseninterface = f
 
         if i is not None and defaultinterface != i:
             if f is not None:
-                self.warn(_("invalid value for ui.interface: %s\n") % (i,))
+                self.warn(_(b"invalid value for ui.interface: %s\n") % (i,))
             else:
                 self.warn(
-                    _("invalid value for ui.interface: %s (using %s)\n")
+                    _(b"invalid value for ui.interface: %s (using %s)\n")
                     % (i, choseninterface)
                 )
         if f is not None and choseninterface != f:
             self.warn(
-                _("invalid value for ui.interface.%s: %s (using %s)\n")
+                _(b"invalid value for ui.interface.%s: %s (using %s)\n")
                 % (feature, f, choseninterface)
             )
 
@@ -1461,7 +1466,7 @@
 
         This function refers to input only; for output, see `ui.formatted()'.
         '''
-        i = self.configbool("ui", "interactive")
+        i = self.configbool(b"ui", b"interactive")
         if i is None:
             # some environments replace stdin without implementing isatty
             # usually those are non-interactive
@@ -1472,9 +1477,9 @@
     def termwidth(self):
         '''how wide is the terminal in columns?
         '''
-        if 'COLUMNS' in encoding.environ:
+        if b'COLUMNS' in encoding.environ:
             try:
-                return int(encoding.environ['COLUMNS'])
+                return int(encoding.environ[b'COLUMNS'])
             except ValueError:
                 pass
         return scmutil.termsize(self)[0]
@@ -1499,7 +1504,7 @@
         if self.plain():
             return False
 
-        i = self.configbool("ui", "formatted")
+        i = self.configbool(b"ui", b"formatted")
         if i is None:
             # some environments replace stdout without implementing isatty
             # usually those are non-interactive
@@ -1507,7 +1512,7 @@
 
         return i
 
-    def _readline(self, prompt=' ', promptopts=None):
+    def _readline(self, prompt=b' ', promptopts=None):
         # Replacing stdin/stdout temporarily is a hard problem on Python 3
         # because they have to be text streams with *no buffering*. Instead,
         # we use rawinput() only if call_readline() will be invoked by
@@ -1530,20 +1535,20 @@
             except Exception:
                 usereadline = False
 
-        if self._colormode == 'win32' or not usereadline:
+        if self._colormode == b'win32' or not usereadline:
             if not promptopts:
                 promptopts = {}
             self._writemsgnobuf(
-                self._fmsgout, prompt, type='prompt', **promptopts
+                self._fmsgout, prompt, type=b'prompt', **promptopts
             )
             self.flush()
-            prompt = ' '
+            prompt = b' '
         else:
-            prompt = self.label(prompt, 'ui.prompt') + ' '
+            prompt = self.label(prompt, b'ui.prompt') + b' '
 
         # prompt ' ' must exist; otherwise readline may delete entire line
         # - http://bugs.python.org/issue12833
-        with self.timeblockedsection('stdio'):
+        with self.timeblockedsection(b'stdio'):
             if usereadline:
                 line = encoding.strtolocal(pycompat.rawinput(prompt))
                 # When stdin is in binary mode on Windows, it can cause
@@ -1560,7 +1565,7 @@
 
         return line
 
-    def prompt(self, msg, default="y"):
+    def prompt(self, msg, default=b"y"):
         """Prompt user with msg, read response.
         If ui is not interactive, the default is returned.
         """
@@ -1569,17 +1574,17 @@
     def _prompt(self, msg, **opts):
         default = opts[r'default']
         if not self.interactive():
-            self._writemsg(self._fmsgout, msg, ' ', type='prompt', **opts)
+            self._writemsg(self._fmsgout, msg, b' ', type=b'prompt', **opts)
             self._writemsg(
-                self._fmsgout, default or '', "\n", type='promptecho'
+                self._fmsgout, default or b'', b"\n", type=b'promptecho'
             )
             return default
         try:
             r = self._readline(prompt=msg, promptopts=opts)
             if not r:
                 r = default
-            if self.configbool('ui', 'promptecho'):
-                self._writemsg(self._fmsgout, r, "\n", type='promptecho')
+            if self.configbool(b'ui', b'promptecho'):
+                self._writemsg(self._fmsgout, r, b"\n", type=b'promptecho')
             return r
         except EOFError:
             raise error.ResponseExpected()
@@ -1606,11 +1611,11 @@
         # except an ampersand followed by a character.
         m = re.match(br'(?s)(.+?)\$\$([^\$]*&[^ \$].*)', prompt)
         msg = m.group(1)
-        choices = [p.strip(' ') for p in m.group(2).split('$$')]
+        choices = [p.strip(b' ') for p in m.group(2).split(b'$$')]
 
         def choicetuple(s):
-            ampidx = s.index('&')
-            return s[ampidx + 1 : ampidx + 2].lower(), s.replace('&', '', 1)
+            ampidx = s.index(b'&')
+            return s[ampidx + 1 : ampidx + 2].lower(), s.replace(b'&', b'', 1)
 
         return (msg, [choicetuple(s) for s in choices])
 
@@ -1632,7 +1637,7 @@
             if r.lower() in resps:
                 return resps.index(r.lower())
             # TODO: shouldn't it be a warning?
-            self._writemsg(self._fmsgout, _("unrecognized response\n"))
+            self._writemsg(self._fmsgout, _(b"unrecognized response\n"))
 
     def getpass(self, prompt=None, default=None):
         if not self.interactive():
@@ -1640,18 +1645,18 @@
         try:
             self._writemsg(
                 self._fmsgerr,
-                prompt or _('password: '),
-                type='prompt',
+                prompt or _(b'password: '),
+                type=b'prompt',
                 password=True,
             )
             # disable getpass() only if explicitly specified. it's still valid
             # to interact with tty even if fin is not a tty.
-            with self.timeblockedsection('stdio'):
-                if self.configbool('ui', 'nontty'):
+            with self.timeblockedsection(b'stdio'):
+                if self.configbool(b'ui', b'nontty'):
                     l = self._fin.readline()
                     if not l:
                         raise EOFError
-                    return l.rstrip('\n')
+                    return l.rstrip(b'\n')
                 else:
                     return getpass.getpass(r'')
         except EOFError:
@@ -1663,21 +1668,21 @@
         This adds an output label of "ui.status".
         '''
         if not self.quiet:
-            self._writemsg(self._fmsgout, type='status', *msg, **opts)
+            self._writemsg(self._fmsgout, type=b'status', *msg, **opts)
 
     def warn(self, *msg, **opts):
         '''write warning message to output (stderr)
 
         This adds an output label of "ui.warning".
         '''
-        self._writemsg(self._fmsgerr, type='warning', *msg, **opts)
+        self._writemsg(self._fmsgerr, type=b'warning', *msg, **opts)
 
     def error(self, *msg, **opts):
         '''write error message to output (stderr)
 
         This adds an output label of "ui.error".
         '''
-        self._writemsg(self._fmsgerr, type='error', *msg, **opts)
+        self._writemsg(self._fmsgerr, type=b'error', *msg, **opts)
 
     def note(self, *msg, **opts):
         '''write note to output (if ui.verbose is True)
@@ -1685,7 +1690,7 @@
         This adds an output label of "ui.note".
         '''
         if self.verbose:
-            self._writemsg(self._fmsgout, type='note', *msg, **opts)
+            self._writemsg(self._fmsgout, type=b'note', *msg, **opts)
 
     def debug(self, *msg, **opts):
         '''write debug message to output (if ui.debugflag is True)
@@ -1693,7 +1698,7 @@
         This adds an output label of "ui.debug".
         '''
         if self.debugflag:
-            self._writemsg(self._fmsgout, type='debug', *msg, **opts)
+            self._writemsg(self._fmsgout, type=b'debug', *msg, **opts)
             self.log(b'debug', b'%s', b''.join(msg))
 
     def edit(
@@ -1708,60 +1713,62 @@
     ):
         if action is None:
             self.develwarn(
-                'action is None but will soon be a required '
-                'parameter to ui.edit()'
+                b'action is None but will soon be a required '
+                b'parameter to ui.edit()'
             )
         extra_defaults = {
-            'prefix': 'editor',
-            'suffix': '.txt',
+            b'prefix': b'editor',
+            b'suffix': b'.txt',
         }
         if extra is not None:
-            if extra.get('suffix') is not None:
+            if extra.get(b'suffix') is not None:
                 self.develwarn(
-                    'extra.suffix is not None but will soon be '
-                    'ignored by ui.edit()'
+                    b'extra.suffix is not None but will soon be '
+                    b'ignored by ui.edit()'
                 )
             extra_defaults.update(extra)
         extra = extra_defaults
 
-        if action == 'diff':
-            suffix = '.diff'
+        if action == b'diff':
+            suffix = b'.diff'
         elif action:
-            suffix = '.%s.hg.txt' % action
+            suffix = b'.%s.hg.txt' % action
         else:
-            suffix = extra['suffix']
+            suffix = extra[b'suffix']
 
         rdir = None
-        if self.configbool('experimental', 'editortmpinhg'):
+        if self.configbool(b'experimental', b'editortmpinhg'):
             rdir = repopath
         (fd, name) = pycompat.mkstemp(
-            prefix='hg-' + extra['prefix'] + '-', suffix=suffix, dir=rdir
+            prefix=b'hg-' + extra[b'prefix'] + b'-', suffix=suffix, dir=rdir
         )
         try:
             f = os.fdopen(fd, r'wb')
             f.write(util.tonativeeol(text))
             f.close()
 
-            environ = {'HGUSER': user}
-            if 'transplant_source' in extra:
-                environ.update({'HGREVISION': hex(extra['transplant_source'])})
-            for label in ('intermediate-source', 'source', 'rebase_source'):
+            environ = {b'HGUSER': user}
+            if b'transplant_source' in extra:
+                environ.update(
+                    {b'HGREVISION': hex(extra[b'transplant_source'])}
+                )
+            for label in (b'intermediate-source', b'source', b'rebase_source'):
                 if label in extra:
-                    environ.update({'HGREVISION': extra[label]})
+                    environ.update({b'HGREVISION': extra[label]})
                     break
             if editform:
-                environ.update({'HGEDITFORM': editform})
+                environ.update({b'HGEDITFORM': editform})
             if pending:
-                environ.update({'HG_PENDING': pending})
+                environ.update({b'HG_PENDING': pending})
 
             editor = self.geteditor()
 
             self.system(
-                "%s \"%s\"" % (editor, name),
+                b"%s \"%s\"" % (editor, name),
                 environ=environ,
                 onerr=error.Abort,
-                errprefix=_("edit failed"),
-                blockedtag='editor',
+                errprefix=_(b"edit failed"),
+                blockedtag=b'editor',
             )
 
             f = open(name, r'rb')
@@ -1791,19 +1798,19 @@
             # Long cmds tend to be because of an absolute path on cmd. Keep
             # the tail end instead
             cmdsuffix = cmd.translate(None, _keepalnum)[-85:]
-            blockedtag = 'unknown_system_' + cmdsuffix
+            blockedtag = b'unknown_system_' + cmdsuffix
         out = self._fout
         if any(s[1] for s in self._bufferstates):
             out = self
         with self.timeblockedsection(blockedtag):
             rc = self._runsystem(cmd, environ=environ, cwd=cwd, out=out)
         if rc and onerr:
-            errmsg = '%s %s' % (
+            errmsg = b'%s %s' % (
                 os.path.basename(cmd.split(None, 1)[0]),
                 procutil.explainexit(rc),
             )
             if errprefix:
-                errmsg = '%s: %s' % (errprefix, errmsg)
+                errmsg = b'%s: %s' % (errprefix, errmsg)
             raise onerr(errmsg)
         return rc
 
@@ -1828,10 +1835,10 @@
 
                 # exclude frame where 'exc' was chained and rethrown from exctb
                 self.write_err(
-                    'Traceback (most recent call last):\n',
-                    ''.join(exctb[:-1]),
-                    ''.join(causetb),
-                    ''.join(exconly),
+                    b'Traceback (most recent call last):\n',
+                    b''.join(exctb[:-1]),
+                    b''.join(causetb),
+                    b''.join(exconly),
                 )
             else:
                 output = traceback.format_exception(exc[0], exc[1], exc[2])
@@ -1840,15 +1847,15 @@
 
     def geteditor(self):
         '''return editor to use'''
-        if pycompat.sysplatform == 'plan9':
+        if pycompat.sysplatform == b'plan9':
             # vi is the MIPS instruction simulator on Plan 9. We
             # instead default to E to plumb commit messages to
             # avoid confusion.
-            editor = 'E'
+            editor = b'E'
         else:
-            editor = 'vi'
-        return encoding.environ.get("HGEDITOR") or self.config(
-            "ui", "editor", editor
+            editor = b'vi'
+        return encoding.environ.get(b"HGEDITOR") or self.config(
+            b"ui", b"editor", editor
         )
 
     @util.propertycache
@@ -1857,7 +1864,7 @@
         if (
             self.quiet
             or self.debugflag
-            or self.configbool('progress', 'disable')
+            or self.configbool(b'progress', b'disable')
             or not progress.shouldprint(self)
         ):
             return None
@@ -1870,7 +1877,7 @@
         if self._progbar is not None and self._progbar.printed:
             self._progbar.clear()
 
-    def progress(self, topic, pos, item="", unit="", total=None):
+    def progress(self, topic, pos, item=b"", unit=b"", total=None):
         '''show a progress message
 
         By default a textual progress bar will be displayed if an operation
@@ -1885,14 +1892,16 @@
         All topics should be marked closed by setting pos to None at
         termination.
         '''
-        self.deprecwarn("use ui.makeprogress() instead of ui.progress()", "5.1")
+        self.deprecwarn(
+            b"use ui.makeprogress() instead of ui.progress()", b"5.1"
+        )
         progress = self.makeprogress(topic, unit, total)
         if pos is not None:
             progress.update(pos, item=item)
         else:
             progress.complete()
 
-    def makeprogress(self, topic, unit="", total=None):
+    def makeprogress(self, topic, unit=b"", total=None):
         """Create a progress helper for the specified topic"""
         if getattr(self._fmsgerr, 'structured', False):
             # channel for machine-readable output with metadata, just send
@@ -1981,25 +1990,26 @@
         Use 'stacklevel' to report the offender some layers further up in the
         stack.
         """
-        if not self.configbool('devel', 'all-warnings'):
-            if config is None or not self.configbool('devel', config):
+        if not self.configbool(b'devel', b'all-warnings'):
+            if config is None or not self.configbool(b'devel', config):
                 return
-        msg = 'devel-warn: ' + msg
+        msg = b'devel-warn: ' + msg
         stacklevel += 1  # get in develwarn
         if self.tracebackflag:
             util.debugstacktrace(msg, stacklevel, self._ferr, self._fout)
             self.log(
-                'develwarn',
-                '%s at:\n%s' % (msg, ''.join(util.getstackframes(stacklevel))),
+                b'develwarn',
+                b'%s at:\n%s'
+                % (msg, b''.join(util.getstackframes(stacklevel))),
             )
         else:
             curframe = inspect.currentframe()
             calframe = inspect.getouterframes(curframe, 2)
             fname, lineno, fmsg = calframe[stacklevel][1:4]
             fname, fmsg = pycompat.sysbytes(fname), pycompat.sysbytes(fmsg)
-            self.write_err('%s at: %s:%d (%s)\n' % (msg, fname, lineno, fmsg))
+            self.write_err(b'%s at: %s:%d (%s)\n' % (msg, fname, lineno, fmsg))
             self.log(
-                'develwarn', '%s at: %s:%d (%s)\n', msg, fname, lineno, fmsg
+                b'develwarn', b'%s at: %s:%d (%s)\n', msg, fname, lineno, fmsg
             )
             curframe = calframe = None  # avoid cycles
 
@@ -2010,15 +2020,15 @@
         - version: last version where the API will be supported,
         """
         if not (
-            self.configbool('devel', 'all-warnings')
-            or self.configbool('devel', 'deprec-warn')
+            self.configbool(b'devel', b'all-warnings')
+            or self.configbool(b'devel', b'deprec-warn')
         ):
             return
         msg += (
-            "\n(compatibility will be dropped after Mercurial-%s,"
-            " update your code.)"
+            b"\n(compatibility will be dropped after Mercurial-%s,"
+            b" update your code.)"
         ) % version
-        self.develwarn(msg, stacklevel=stacklevel, config='deprec-warn')
+        self.develwarn(msg, stacklevel=stacklevel, config=b'deprec-warn')
 
     def exportableenviron(self):
         """The environment variables that are safe to export, e.g. through
@@ -2027,7 +2037,7 @@
         return self._exportableenviron
 
     @contextlib.contextmanager
-    def configoverride(self, overrides, source=""):
+    def configoverride(self, overrides, source=b""):
         """Context manager for temporary config overrides
         `overrides` must be a dict of the following structure:
         {(section, name) : value}"""
@@ -2042,8 +2052,8 @@
                 self.restoreconfig(backup)
             # just restoring ui.quiet config to the previous value is not enough
             # as it does not update ui.quiet class member
-            if ('ui', 'quiet') in overrides:
-                self.fixconfig(section='ui')
+            if (b'ui', b'quiet') in overrides:
+                self.fixconfig(section=b'ui')
 
 
 class paths(dict):
@@ -2056,11 +2066,11 @@
     def __init__(self, ui):
         dict.__init__(self)
 
-        for name, loc in ui.configitems('paths', ignoresub=True):
+        for name, loc in ui.configitems(b'paths', ignoresub=True):
             # No location is the same as not existing.
             if not loc:
                 continue
-            loc, sub = ui.configsuboptions('paths', name)
+            loc, sub = ui.configsuboptions(b'paths', name)
             self[name] = path(ui, name, rawloc=loc, suboptions=sub)
 
     def getpath(self, name, default=None):
@@ -2098,7 +2108,7 @@
                 # We don't pass sub-options in, so no need to pass ui instance.
                 return path(None, None, rawloc=name)
             except ValueError:
-                raise error.RepoError(_('repository %s does not exist') % name)
+                raise error.RepoError(_(b'repository %s does not exist') % name)
 
 
 _pathsuboptions = {}
@@ -2126,19 +2136,22 @@
     return register
 
 
-@pathsuboption('pushurl', 'pushloc')
+@pathsuboption(b'pushurl', b'pushloc')
 def pushurlpathoption(ui, path, value):
     u = util.url(value)
     # Actually require a URL.
     if not u.scheme:
-        ui.warn(_('(paths.%s:pushurl not a URL; ignoring)\n') % path.name)
+        ui.warn(_(b'(paths.%s:pushurl not a URL; ignoring)\n') % path.name)
         return None
 
     # Don't support the #foo syntax in the push URL to declare branch to
     # push.
     if u.fragment:
         ui.warn(
-            _('("#fragment" in paths.%s:pushurl not supported; ' 'ignoring)\n')
+            _(
+                b'("#fragment" in paths.%s:pushurl not supported; '
+                b'ignoring)\n'
+            )
             % path.name
         )
         u.fragment = None
@@ -2146,7 +2159,7 @@
     return bytes(u)
 
 
-@pathsuboption('pushrev', 'pushrev')
+@pathsuboption(b'pushrev', b'pushrev')
 def pushrevpathoption(ui, path, value):
     return value
 
@@ -2167,7 +2180,7 @@
         ``ValueError`` is raised.
         """
         if not rawloc:
-            raise ValueError('rawloc must be defined')
+            raise ValueError(b'rawloc must be defined')
 
         # Locations may define branches via syntax <base>#<branch>.
         u = util.url(rawloc)
@@ -2181,13 +2194,14 @@
 
         self.name = name
         self.rawloc = rawloc
-        self.loc = '%s' % u
+        self.loc = b'%s' % u
 
         # When given a raw location but not a symbolic name, validate the
         # location is valid.
         if not name and not u.scheme and not self._isvalidlocalpath(self.loc):
             raise ValueError(
-                'location is not a URL or path to a local ' 'repo: %s' % rawloc
+                b'location is not a URL or path to a local '
+                b'repo: %s' % rawloc
             )
 
         suboptions = suboptions or {}
@@ -2209,7 +2223,7 @@
         'valid' in this case (like when pulling from a git repo into a hg
         one)."""
         try:
-            return os.path.isdir(os.path.join(path, '.hg'))
+            return os.path.isdir(os.path.join(path, b'.hg'))
         # Python 2 may return TypeError. Python 3, ValueError.
         except (TypeError, ValueError):
             return False
@@ -2270,5 +2284,5 @@
     """
     # TODO: maybe change 'type' to a mandatory option
     if r'type' in opts and not getattr(dest, 'structured', False):
-        opts[r'label'] = opts.get(r'label', '') + ' ui.%s' % opts.pop(r'type')
+        opts[r'label'] = opts.get(r'label', b'') + b' ui.%s' % opts.pop(r'type')
     write(dest, *args, **opts)