diff -r 2372284d9457 -r 687b865b95ad hgext/fix.py --- 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)