hgext/fix.py
changeset 43077 687b865b95ad
parent 43076 2372284d9457
child 43087 66f2cc210a29
--- a/hgext/fix.py	Sun Oct 06 09:45:02 2019 -0400
+++ b/hgext/fix.py	Sun Oct 06 09:48:39 2019 -0400
@@ -157,7 +157,7 @@
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
 # leave the attribute unspecified.
-testedwith = 'ships-with-hg-core'
+testedwith = b'ships-with-hg-core'
 
 cmdtable = {}
 command = registrar.command(cmdtable)
@@ -167,61 +167,61 @@
 
 # Register the suboptions allowed for each configured fixer, and default values.
 FIXER_ATTRS = {
-    'command': None,
-    'linerange': None,
-    'pattern': None,
-    'priority': 0,
-    'metadata': 'false',
-    'skipclean': 'true',
-    'enabled': 'true',
+    b'command': None,
+    b'linerange': None,
+    b'pattern': None,
+    b'priority': 0,
+    b'metadata': b'false',
+    b'skipclean': b'true',
+    b'enabled': b'true',
 }
 
 for key, default in FIXER_ATTRS.items():
-    configitem('fix', '.*(:%s)?' % key, default=default, generic=True)
+    configitem(b'fix', b'.*(:%s)?' % key, default=default, generic=True)
 
 # A good default size allows most source code files to be fixed, but avoids
 # letting fixer tools choke on huge inputs, which could be surprising to the
 # user.
-configitem('fix', 'maxfilesize', default='2MB')
+configitem(b'fix', b'maxfilesize', default=b'2MB')
 
 # Allow fix commands to exit non-zero if an executed fixer tool exits non-zero.
 # This helps users do shell scripts that stop when a fixer tool signals a
 # problem.
-configitem('fix', 'failure', default='continue')
+configitem(b'fix', b'failure', default=b'continue')
 
 
 def checktoolfailureaction(ui, message, hint=None):
     """Abort with 'message' if fix.failure=abort"""
-    action = ui.config('fix', 'failure')
-    if action not in ('continue', 'abort'):
+    action = ui.config(b'fix', b'failure')
+    if action not in (b'continue', b'abort'):
         raise error.Abort(
-            _('unknown fix.failure action: %s') % (action,),
-            hint=_('use "continue" or "abort"'),
+            _(b'unknown fix.failure action: %s') % (action,),
+            hint=_(b'use "continue" or "abort"'),
         )
-    if action == 'abort':
+    if action == b'abort':
         raise error.Abort(message, hint=hint)
 
 
-allopt = ('', 'all', False, _('fix all non-public non-obsolete revisions'))
+allopt = (b'', b'all', False, _(b'fix all non-public non-obsolete revisions'))
 baseopt = (
-    '',
-    'base',
+    b'',
+    b'base',
     [],
     _(
-        'revisions to diff against (overrides automatic '
-        'selection, and applies to every revision being '
-        'fixed)'
+        b'revisions to diff against (overrides automatic '
+        b'selection, and applies to every revision being '
+        b'fixed)'
     ),
-    _('REV'),
+    _(b'REV'),
 )
-revopt = ('r', 'rev', [], _('revisions to fix'), _('REV'))
-wdiropt = ('w', 'working-dir', False, _('fix the working directory'))
-wholeopt = ('', 'whole', False, _('always fix every line of a file'))
-usage = _('[OPTION]... [FILE]...')
+revopt = (b'r', b'rev', [], _(b'revisions to fix'), _(b'REV'))
+wdiropt = (b'w', b'working-dir', False, _(b'fix the working directory'))
+wholeopt = (b'', b'whole', False, _(b'always fix every line of a file'))
+usage = _(b'[OPTION]... [FILE]...')
 
 
 @command(
-    'fix',
+    b'fix',
     [allopt, baseopt, revopt, wdiropt, wholeopt],
     usage,
     helpcategory=command.CATEGORY_FILE_CONTENTS,
@@ -250,12 +250,12 @@
     override this default behavior, though it is not usually desirable to do so.
     """
     opts = pycompat.byteskwargs(opts)
-    if opts['all']:
-        if opts['rev']:
-            raise error.Abort(_('cannot specify both "--rev" and "--all"'))
-        opts['rev'] = ['not public() and not obsolete()']
-        opts['working_dir'] = True
-    with repo.wlock(), repo.lock(), repo.transaction('fix'):
+    if opts[b'all']:
+        if opts[b'rev']:
+            raise error.Abort(_(b'cannot specify both "--rev" and "--all"'))
+        opts[b'rev'] = [b'not public() and not obsolete()']
+        opts[b'working_dir'] = True
+    with repo.wlock(), repo.lock(), repo.transaction(b'fix'):
         revstofix = getrevstofix(ui, repo, opts)
         basectxs = getbasectxs(repo, opts, revstofix)
         workqueue, numitems = getworkqueue(
@@ -297,7 +297,7 @@
         wdirwritten = False
         commitorder = sorted(revstofix, reverse=True)
         with ui.makeprogress(
-            topic=_('fixing'), unit=_('files'), total=sum(numitems.values())
+            topic=_(b'fixing'), unit=_(b'files'), total=sum(numitems.values())
         ) as progress:
             for rev, path, filerevmetadata, newdata in results:
                 progress.increment(item=path)
@@ -306,12 +306,12 @@
                 if newdata is not None:
                     filedata[rev][path] = newdata
                     hookargs = {
-                        'rev': rev,
-                        'path': path,
-                        'metadata': filerevmetadata,
+                        b'rev': rev,
+                        b'path': path,
+                        b'metadata': filerevmetadata,
                     }
                     repo.hook(
-                        'postfixfile',
+                        b'postfixfile',
                         throw=False,
                         **pycompat.strkwargs(hookargs)
                     )
@@ -332,11 +332,11 @@
 
         cleanup(repo, replacements, wdirwritten)
         hookargs = {
-            'replacements': replacements,
-            'wdirwritten': wdirwritten,
-            'metadata': aggregatemetadata,
+            b'replacements': replacements,
+            b'wdirwritten': wdirwritten,
+            b'metadata': aggregatemetadata,
         }
-        repo.hook('postfix', throw=True, **pycompat.strkwargs(hookargs))
+        repo.hook(b'postfix', throw=True, **pycompat.strkwargs(hookargs))
 
 
 def cleanup(repo, replacements, wdirwritten):
@@ -353,7 +353,7 @@
     effects of the command, though we choose not to output anything here.
     """
     replacements = {prec: [succ] for prec, succ in replacements.iteritems()}
-    scmutil.cleanupnodes(repo, replacements, 'fix', fixphase=True)
+    scmutil.cleanupnodes(repo, replacements, b'fix', fixphase=True)
 
 
 def getworkqueue(ui, repo, pats, opts, revstofix, basectxs):
@@ -375,7 +375,7 @@
     """
     workqueue = []
     numitems = collections.defaultdict(int)
-    maxfilesize = ui.configbytes('fix', 'maxfilesize')
+    maxfilesize = ui.configbytes(b'fix', b'maxfilesize')
     for rev in sorted(revstofix):
         fixctx = repo[rev]
         match = scmutil.match(fixctx, pats, opts)
@@ -387,7 +387,7 @@
                 continue
             if fctx.size() > maxfilesize:
                 ui.warn(
-                    _('ignoring file larger than %s: %s\n')
+                    _(b'ignoring file larger than %s: %s\n')
                     % (util.bytecount(maxfilesize), path)
                 )
                 continue
@@ -398,29 +398,29 @@
 
 def getrevstofix(ui, repo, opts):
     """Returns the set of revision numbers that should be fixed"""
-    revs = set(scmutil.revrange(repo, opts['rev']))
+    revs = set(scmutil.revrange(repo, opts[b'rev']))
     for rev in revs:
         checkfixablectx(ui, repo, repo[rev])
     if revs:
         cmdutil.checkunfinished(repo)
         checknodescendants(repo, revs)
-    if opts.get('working_dir'):
+    if opts.get(b'working_dir'):
         revs.add(wdirrev)
         if list(merge.mergestate.read(repo).unresolved()):
-            raise error.Abort('unresolved conflicts', hint="use 'hg resolve'")
+            raise error.Abort(b'unresolved conflicts', hint=b"use 'hg resolve'")
     if not revs:
         raise error.Abort(
-            'no changesets specified', hint='use --rev or --working-dir'
+            b'no changesets specified', hint=b'use --rev or --working-dir'
         )
     return revs
 
 
 def checknodescendants(repo, revs):
     if not obsolete.isenabled(repo, obsolete.allowunstableopt) and repo.revs(
-        '(%ld::) - (%ld)', revs, revs
+        b'(%ld::) - (%ld)', revs, revs
     ):
         raise error.Abort(
-            _('can only fix a changeset together ' 'with all its descendants')
+            _(b'can only fix a changeset together ' b'with all its descendants')
         )
 
 
@@ -428,15 +428,18 @@
     """Aborts if the revision shouldn't be replaced with a fixed one."""
     if not ctx.mutable():
         raise error.Abort(
-            'can\'t fix immutable changeset %s' % (scmutil.formatchangeid(ctx),)
+            b'can\'t fix immutable changeset %s'
+            % (scmutil.formatchangeid(ctx),)
         )
     if ctx.obsolete():
         # It would be better to actually check if the revision has a successor.
         allowdivergence = ui.configbool(
-            'experimental', 'evolution.allowdivergence'
+            b'experimental', b'evolution.allowdivergence'
         )
         if not allowdivergence:
-            raise error.Abort('fixing obsolete revision could cause divergence')
+            raise error.Abort(
+                b'fixing obsolete revision could cause divergence'
+            )
 
 
 def pathstofix(ui, repo, pats, opts, match, basectxs, fixctx):
@@ -473,10 +476,10 @@
     Another way to understand this is that we exclude line ranges that are
     common to the file in all base contexts.
     """
-    if opts.get('whole'):
+    if opts.get(b'whole'):
         # Return a range containing all lines. Rely on the diff implementation's
         # idea of how many lines are in the file, instead of reimplementing it.
-        return difflineranges('', content2)
+        return difflineranges(b'', content2)
 
     rangeslist = []
     for basectx in basectxs:
@@ -484,7 +487,7 @@
         if basepath in basectx:
             content1 = basectx[basepath].data()
         else:
-            content1 = ''
+            content1 = b''
         rangeslist.extend(difflineranges(content1, content2))
     return unionranges(rangeslist)
 
@@ -566,7 +569,7 @@
     ranges = []
     for lines, kind in mdiff.allblocks(content1, content2):
         firstline, lastline = lines[2:4]
-        if kind == '!' and firstline != lastline:
+        if kind == b'!' and firstline != lastline:
             ranges.append((firstline + 1, lastline))
     return ranges
 
@@ -581,8 +584,8 @@
     """
     # The --base flag overrides the usual logic, and we give every revision
     # exactly the set of baserevs that the user specified.
-    if opts.get('base'):
-        baserevs = set(scmutil.revrange(repo, opts.get('base')))
+    if opts.get(b'base'):
+        baserevs = set(scmutil.revrange(repo, opts.get(b'base')))
         if not baserevs:
             baserevs = {nullrev}
         basectxs = {repo[rev] for rev in baserevs}
@@ -621,7 +624,7 @@
             command = fixer.command(ui, path, ranges)
             if command is None:
                 continue
-            ui.debug('subprocess: %s\n' % (command,))
+            ui.debug(b'subprocess: %s\n' % (command,))
             proc = subprocess.Popen(
                 procutil.tonativestr(command),
                 shell=True,
@@ -636,11 +639,11 @@
             newerdata = stdout
             if fixer.shouldoutputmetadata():
                 try:
-                    metadatajson, newerdata = stdout.split('\0', 1)
+                    metadatajson, newerdata = stdout.split(b'\0', 1)
                     metadata[fixername] = json.loads(metadatajson)
                 except ValueError:
                     ui.warn(
-                        _('ignored invalid output from fixer tool: %s\n')
+                        _(b'ignored invalid output from fixer tool: %s\n')
                         % (fixername,)
                     )
                     continue
@@ -650,14 +653,14 @@
                 newdata = newerdata
             else:
                 if not stderr:
-                    message = _('exited with status %d\n') % (proc.returncode,)
+                    message = _(b'exited with status %d\n') % (proc.returncode,)
                     showstderr(ui, fixctx.rev(), fixername, message)
                 checktoolfailureaction(
                     ui,
-                    _('no fixes will be applied'),
+                    _(b'no fixes will be applied'),
                     hint=_(
-                        'use --config fix.failure=continue to apply any '
-                        'successful fixes anyway'
+                        b'use --config fix.failure=continue to apply any '
+                        b'successful fixes anyway'
                     ),
                 )
     return metadata, newdata
@@ -671,14 +674,14 @@
     space and would tend to be included in the error message if they were
     relevant.
     """
-    for line in re.split('[\r\n]+', stderr):
+    for line in re.split(b'[\r\n]+', stderr):
         if line:
-            ui.warn('[')
+            ui.warn(b'[')
             if rev is None:
-                ui.warn(_('wdir'), label='evolve.rev')
+                ui.warn(_(b'wdir'), label=b'evolve.rev')
             else:
-                ui.warn((str(rev)), label='evolve.rev')
-            ui.warn('] %s: %s\n' % (fixername, line))
+                ui.warn((str(rev)), label=b'evolve.rev')
+            ui.warn(b'] %s: %s\n' % (fixername, line))
 
 
 def writeworkingdir(repo, ctx, filedata, replacements):
@@ -694,7 +697,7 @@
     for path, data in filedata.iteritems():
         fctx = ctx[path]
         fctx.write(data, fctx.flags())
-        if repo.dirstate[path] == 'n':
+        if repo.dirstate[path] == b'n':
             repo.dirstate.normallookup(path)
 
     oldparentnodes = repo.dirstate.parents()
@@ -757,7 +760,7 @@
         )
 
     extra = ctx.extra().copy()
-    extra['fix_source'] = ctx.hex()
+    extra[b'fix_source'] = ctx.hex()
 
     memctx = context.memctx(
         repo,
@@ -774,7 +777,7 @@
     sucnode = memctx.commit()
     prenode = ctx.node()
     if prenode == sucnode:
-        ui.debug('node %s already existed\n' % (ctx.hex()))
+        ui.debug(b'node %s already existed\n' % (ctx.hex()))
     else:
         replacements[ctx.node()] = sucnode
 
@@ -788,11 +791,11 @@
     fixers = {}
     for name in fixernames(ui):
         fixers[name] = Fixer()
-        attrs = ui.configsuboptions('fix', name)[1]
+        attrs = ui.configsuboptions(b'fix', name)[1]
         for key, default in FIXER_ATTRS.items():
             setattr(
                 fixers[name],
-                pycompat.sysstr('_' + key),
+                pycompat.sysstr(b'_' + key),
                 attrs.get(key, default),
             )
         fixers[name]._priority = int(fixers[name]._priority)
@@ -805,11 +808,11 @@
         # default.
         if fixers[name]._pattern is None:
             ui.warn(
-                _('fixer tool has no pattern configuration: %s\n') % (name,)
+                _(b'fixer tool has no pattern configuration: %s\n') % (name,)
             )
             del fixers[name]
         elif not fixers[name]._enabled:
-            ui.debug('ignoring disabled fixer tool: %s\n' % (name,))
+            ui.debug(b'ignoring disabled fixer tool: %s\n' % (name,))
             del fixers[name]
     return collections.OrderedDict(
         sorted(fixers.items(), key=lambda item: item[1]._priority, reverse=True)
@@ -819,9 +822,9 @@
 def fixernames(ui):
     """Returns the names of [fix] config options that have suboptions"""
     names = set()
-    for k, v in ui.configitems('fix'):
-        if ':' in k:
-            names.add(k.split(':', 1)[0])
+    for k, v in ui.configitems(b'fix'):
+        if b':' in k:
+            names.add(k.split(b':', 1)[0])
     return names
 
 
@@ -849,7 +852,7 @@
             expand(
                 ui,
                 self._command,
-                {'rootpath': path, 'basename': os.path.basename(path)},
+                {b'rootpath': path, b'basename': os.path.basename(path)},
             )
         ]
         if self._linerange:
@@ -858,6 +861,8 @@
                 return None
             for first, last in ranges:
                 parts.append(
-                    expand(ui, self._linerange, {'first': first, 'last': last})
+                    expand(
+                        ui, self._linerange, {b'first': first, b'last': last}
+                    )
                 )
-        return ' '.join(parts)
+        return b' '.join(parts)