hgext/fix.py
author Yuya Nishihara <yuya@tcha.org>
Sun, 29 Jul 2018 16:25:51 +0900
branchstable
changeset 38758 774f92710a81
parent 38591 f068495a1c28
child 38811 260c17eaf3f7
permissions -rw-r--r--
fileset: suppress EACCES while reading arbitrary paths via filectx API On Windows, EACCES is raised in place of EISDIR. This patch simply adds EACCES to the list of errors to be ignored since I think it's okay for filesets to treat inaccessible working-copy files as not existing.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
     1
# fix - rewrite file content in changesets and working copy
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
     2
#
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
     3
# Copyright 2018 Google LLC.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
     4
#
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
     7
"""rewrite file content in changesets or working copy (EXPERIMENTAL)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
     8
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
     9
Provides a command that runs configured tools on the contents of modified files,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    10
writing back any fixes to the working copy or replacing changesets.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    11
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    12
Here is an example configuration that causes :hg:`fix` to apply automatic
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    13
formatting fixes to modified lines in C++ code::
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    14
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    15
  [fix]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    16
  clang-format:command=clang-format --assume-filename={rootpath}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    17
  clang-format:linerange=--lines={first}:{last}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    18
  clang-format:fileset=set:**.cpp or **.hpp
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    19
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    20
The :command suboption forms the first part of the shell command that will be
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    21
used to fix a file. The content of the file is passed on standard input, and the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    22
fixed file content is expected on standard output. If there is any output on
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    23
standard error, the file will not be affected. Some values may be substituted
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    24
into the command::
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    25
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    26
  {rootpath}  The path of the file being fixed, relative to the repo root
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    27
  {basename}  The name of the file being fixed, without the directory path
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    28
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    29
If the :linerange suboption is set, the tool will only be run if there are
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    30
changed lines in a file. The value of this suboption is appended to the shell
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    31
command once for every range of changed lines in the file. Some values may be
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    32
substituted into the command::
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    33
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    34
  {first}   The 1-based line number of the first line in the modified range
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    35
  {last}    The 1-based line number of the last line in the modified range
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    36
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    37
The :fileset suboption determines which files will be passed through each
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    38
configured tool. See :hg:`help fileset` for possible values. If there are file
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    39
arguments to :hg:`fix`, the intersection of these filesets is used.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    40
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    41
There is also a configurable limit for the maximum size of file that will be
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    42
processed by :hg:`fix`::
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    43
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    44
  [fix]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    45
  maxfilesize=2MB
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    46
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    47
"""
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    48
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    49
from __future__ import absolute_import
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    50
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    51
import collections
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    52
import itertools
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    53
import os
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    54
import re
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    55
import subprocess
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    56
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    57
from mercurial.i18n import _
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    58
from mercurial.node import nullrev
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    59
from mercurial.node import wdirrev
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    60
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    61
from mercurial import (
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    62
    cmdutil,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    63
    context,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    64
    copies,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    65
    error,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    66
    mdiff,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    67
    merge,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    68
    obsolete,
37618
1edf3738e000 fix: port most of the way to python 3
Augie Fackler <augie@google.com>
parents: 37595
diff changeset
    69
    pycompat,
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    70
    registrar,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    71
    scmutil,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    72
    util,
38537
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
    73
    worker,
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    74
)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    75
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    76
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    77
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    78
# be specifying the version(s) of Mercurial they are tested with, or
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    79
# leave the attribute unspecified.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    80
testedwith = 'ships-with-hg-core'
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    81
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    82
cmdtable = {}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    83
command = registrar.command(cmdtable)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    84
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    85
configtable = {}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    86
configitem = registrar.configitem(configtable)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    87
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    88
# Register the suboptions allowed for each configured fixer.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    89
FIXER_ATTRS = ('command', 'linerange', 'fileset')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    90
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    91
for key in FIXER_ATTRS:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    92
    configitem('fix', '.*(:%s)?' % key, default=None, generic=True)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    93
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    94
# A good default size allows most source code files to be fixed, but avoids
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    95
# letting fixer tools choke on huge inputs, which could be surprising to the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    96
# user.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    97
configitem('fix', 'maxfilesize', default='2MB')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    98
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    99
@command('fix',
37595
e2506748b47f fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents: 37215
diff changeset
   100
    [('', 'all', False, _('fix all non-public non-obsolete revisions')),
e2506748b47f fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents: 37215
diff changeset
   101
     ('', 'base', [], _('revisions to diff against (overrides automatic '
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   102
                        'selection, and applies to every revision being '
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   103
                        'fixed)'), _('REV')),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   104
     ('r', 'rev', [], _('revisions to fix'), _('REV')),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   105
     ('w', 'working-dir', False, _('fix the working directory')),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   106
     ('', 'whole', False, _('always fix every line of a file'))],
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   107
    _('[OPTION]... [FILE]...'))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   108
def fix(ui, repo, *pats, **opts):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   109
    """rewrite file content in changesets or working directory
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   110
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   111
    Runs any configured tools to fix the content of files. Only affects files
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   112
    with changes, unless file arguments are provided. Only affects changed lines
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   113
    of files, unless the --whole flag is used. Some tools may always affect the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   114
    whole file regardless of --whole.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   115
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   116
    If revisions are specified with --rev, those revisions will be checked, and
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   117
    they may be replaced with new revisions that have fixed file content.  It is
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   118
    desirable to specify all descendants of each specified revision, so that the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   119
    fixes propagate to the descendants. If all descendants are fixed at the same
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   120
    time, no merging, rebasing, or evolution will be required.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   121
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   122
    If --working-dir is used, files with uncommitted changes in the working copy
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   123
    will be fixed. If the checked-out revision is also fixed, the working
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   124
    directory will update to the replacement revision.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   125
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   126
    When determining what lines of each file to fix at each revision, the whole
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   127
    set of revisions being fixed is considered, so that fixes to earlier
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   128
    revisions are not forgotten in later ones. The --base flag can be used to
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   129
    override this default behavior, though it is not usually desirable to do so.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   130
    """
37618
1edf3738e000 fix: port most of the way to python 3
Augie Fackler <augie@google.com>
parents: 37595
diff changeset
   131
    opts = pycompat.byteskwargs(opts)
37595
e2506748b47f fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents: 37215
diff changeset
   132
    if opts['all']:
e2506748b47f fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents: 37215
diff changeset
   133
        if opts['rev']:
e2506748b47f fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents: 37215
diff changeset
   134
            raise error.Abort(_('cannot specify both "--rev" and "--all"'))
e2506748b47f fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents: 37215
diff changeset
   135
        opts['rev'] = ['not public() and not obsolete()']
e2506748b47f fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents: 37215
diff changeset
   136
        opts['working_dir'] = True
38426
c1f4364f9336 fix: include cleanupnodes() in transaction
Martin von Zweigbergk <martinvonz@google.com>
parents: 37774
diff changeset
   137
    with repo.wlock(), repo.lock(), repo.transaction('fix'):
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   138
        revstofix = getrevstofix(ui, repo, opts)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   139
        basectxs = getbasectxs(repo, opts, revstofix)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   140
        workqueue, numitems = getworkqueue(ui, repo, pats, opts, revstofix,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   141
                                           basectxs)
38537
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   142
        fixers = getfixers(ui)
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   143
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   144
        # There are no data dependencies between the workers fixing each file
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   145
        # revision, so we can use all available parallelism.
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   146
        def getfixes(items):
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   147
            for rev, path in items:
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   148
                ctx = repo[rev]
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   149
                olddata = ctx[path].data()
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   150
                newdata = fixfile(ui, opts, fixers, ctx, path, basectxs[rev])
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   151
                # Don't waste memory/time passing unchanged content back, but
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   152
                # produce one result per item either way.
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   153
                yield (rev, path, newdata if newdata != olddata else None)
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   154
        results = worker.worker(ui, 1.0, getfixes, tuple(), workqueue)
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   155
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   156
        # We have to hold on to the data for each successor revision in memory
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   157
        # until all its parents are committed. We ensure this by committing and
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   158
        # freeing memory for the revisions in some topological order. This
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   159
        # leaves a little bit of memory efficiency on the table, but also makes
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   160
        # the tests deterministic. It might also be considered a feature since
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   161
        # it makes the results more easily reproducible.
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   162
        filedata = collections.defaultdict(dict)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   163
        replacements = {}
38537
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   164
        commitorder = sorted(revstofix, reverse=True)
38538
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   165
        with ui.makeprogress(topic=_('fixing'), unit=_('files'),
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   166
                             total=sum(numitems.values())) as progress:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   167
            for rev, path, newdata in results:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   168
                progress.increment(item=path)
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   169
                if newdata is not None:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   170
                    filedata[rev][path] = newdata
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   171
                numitems[rev] -= 1
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   172
                # Apply the fixes for this and any other revisions that are
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   173
                # ready and sitting at the front of the queue. Using a loop here
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   174
                # prevents the queue from being blocked by the first revision to
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   175
                # be ready out of order.
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   176
                while commitorder and not numitems[commitorder[-1]]:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   177
                    rev = commitorder.pop()
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   178
                    ctx = repo[rev]
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   179
                    if rev == wdirrev:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   180
                        writeworkingdir(repo, ctx, filedata[rev], replacements)
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   181
                    else:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   182
                        replacerev(ui, repo, ctx, filedata[rev], replacements)
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   183
                    del filedata[rev]
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   184
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   185
        replacements = {prec: [succ] for prec, succ in replacements.iteritems()}
38429
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   186
        scmutil.cleanupnodes(repo, replacements, 'fix', fixphase=True)
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   187
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   188
def getworkqueue(ui, repo, pats, opts, revstofix, basectxs):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   189
    """"Constructs the list of files to be fixed at specific revisions
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   190
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   191
    It is up to the caller how to consume the work items, and the only
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   192
    dependence between them is that replacement revisions must be committed in
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   193
    topological order. Each work item represents a file in the working copy or
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   194
    in some revision that should be fixed and written back to the working copy
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   195
    or into a replacement revision.
38537
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   196
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   197
    Work items for the same revision are grouped together, so that a worker
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   198
    pool starting with the first N items in parallel is likely to finish the
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   199
    first revision's work before other revisions. This can allow us to write
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   200
    the result to disk and reduce memory footprint. At time of writing, the
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   201
    partition strategy in worker.py seems favorable to this. We also sort the
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   202
    items by ascending revision number to match the order in which we commit
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   203
    the fixes later.
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   204
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   205
    workqueue = []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   206
    numitems = collections.defaultdict(int)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   207
    maxfilesize = ui.configbytes('fix', 'maxfilesize')
38537
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38429
diff changeset
   208
    for rev in sorted(revstofix):
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   209
        fixctx = repo[rev]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   210
        match = scmutil.match(fixctx, pats, opts)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   211
        for path in pathstofix(ui, repo, pats, opts, match, basectxs[rev],
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   212
                               fixctx):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   213
            if path not in fixctx:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   214
                continue
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   215
            fctx = fixctx[path]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   216
            if fctx.islink():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   217
                continue
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   218
            if fctx.size() > maxfilesize:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   219
                ui.warn(_('ignoring file larger than %s: %s\n') %
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   220
                        (util.bytecount(maxfilesize), path))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   221
                continue
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   222
            workqueue.append((rev, path))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   223
            numitems[rev] += 1
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   224
    return workqueue, numitems
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   225
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   226
def getrevstofix(ui, repo, opts):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   227
    """Returns the set of revision numbers that should be fixed"""
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   228
    revs = set(scmutil.revrange(repo, opts['rev']))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   229
    for rev in revs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   230
        checkfixablectx(ui, repo, repo[rev])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   231
    if revs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   232
        cmdutil.checkunfinished(repo)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   233
        checknodescendants(repo, revs)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   234
    if opts.get('working_dir'):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   235
        revs.add(wdirrev)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   236
        if list(merge.mergestate.read(repo).unresolved()):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   237
            raise error.Abort('unresolved conflicts', hint="use 'hg resolve'")
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   238
    if not revs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   239
        raise error.Abort(
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   240
            'no changesets specified', hint='use --rev or --working-dir')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   241
    return revs
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   242
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   243
def checknodescendants(repo, revs):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   244
    if (not obsolete.isenabled(repo, obsolete.allowunstableopt) and
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   245
        repo.revs('(%ld::) - (%ld)', revs, revs)):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   246
        raise error.Abort(_('can only fix a changeset together '
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   247
                            'with all its descendants'))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   248
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   249
def checkfixablectx(ui, repo, ctx):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   250
    """Aborts if the revision shouldn't be replaced with a fixed one."""
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   251
    if not ctx.mutable():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   252
        raise error.Abort('can\'t fix immutable changeset %s' %
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   253
                          (scmutil.formatchangeid(ctx),))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   254
    if ctx.obsolete():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   255
        # It would be better to actually check if the revision has a successor.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   256
        allowdivergence = ui.configbool('experimental',
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   257
                                        'evolution.allowdivergence')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   258
        if not allowdivergence:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   259
            raise error.Abort('fixing obsolete revision could cause divergence')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   260
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   261
def pathstofix(ui, repo, pats, opts, match, basectxs, fixctx):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   262
    """Returns the set of files that should be fixed in a context
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   263
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   264
    The result depends on the base contexts; we include any file that has
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   265
    changed relative to any of the base contexts. Base contexts should be
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   266
    ancestors of the context being fixed.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   267
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   268
    files = set()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   269
    for basectx in basectxs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   270
        stat = repo.status(
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   271
            basectx, fixctx, match=match, clean=bool(pats), unknown=bool(pats))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   272
        files.update(
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   273
            set(itertools.chain(stat.added, stat.modified, stat.clean,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   274
                                stat.unknown)))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   275
    return files
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   276
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   277
def lineranges(opts, path, basectxs, fixctx, content2):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   278
    """Returns the set of line ranges that should be fixed in a file
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   279
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   280
    Of the form [(10, 20), (30, 40)].
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   281
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   282
    This depends on the given base contexts; we must consider lines that have
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   283
    changed versus any of the base contexts, and whether the file has been
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   284
    renamed versus any of them.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   285
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   286
    Another way to understand this is that we exclude line ranges that are
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   287
    common to the file in all base contexts.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   288
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   289
    if opts.get('whole'):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   290
        # Return a range containing all lines. Rely on the diff implementation's
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   291
        # idea of how many lines are in the file, instead of reimplementing it.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   292
        return difflineranges('', content2)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   293
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   294
    rangeslist = []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   295
    for basectx in basectxs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   296
        basepath = copies.pathcopies(basectx, fixctx).get(path, path)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   297
        if basepath in basectx:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   298
            content1 = basectx[basepath].data()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   299
        else:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   300
            content1 = ''
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   301
        rangeslist.extend(difflineranges(content1, content2))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   302
    return unionranges(rangeslist)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   303
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   304
def unionranges(rangeslist):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   305
    """Return the union of some closed intervals
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   306
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   307
    >>> unionranges([])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   308
    []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   309
    >>> unionranges([(1, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   310
    [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   311
    >>> unionranges([(1, 100), (1, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   312
    [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   313
    >>> unionranges([(1, 100), (2, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   314
    [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   315
    >>> unionranges([(1, 99), (1, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   316
    [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   317
    >>> unionranges([(1, 100), (40, 60)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   318
    [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   319
    >>> unionranges([(1, 49), (50, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   320
    [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   321
    >>> unionranges([(1, 48), (50, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   322
    [(1, 48), (50, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   323
    >>> unionranges([(1, 2), (3, 4), (5, 6)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   324
    [(1, 6)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   325
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   326
    rangeslist = sorted(set(rangeslist))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   327
    unioned = []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   328
    if rangeslist:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   329
        unioned, rangeslist = [rangeslist[0]], rangeslist[1:]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   330
    for a, b in rangeslist:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   331
        c, d = unioned[-1]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   332
        if a > d + 1:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   333
            unioned.append((a, b))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   334
        else:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   335
            unioned[-1] = (c, max(b, d))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   336
    return unioned
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   337
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   338
def difflineranges(content1, content2):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   339
    """Return list of line number ranges in content2 that differ from content1.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   340
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   341
    Line numbers are 1-based. The numbers are the first and last line contained
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   342
    in the range. Single-line ranges have the same line number for the first and
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   343
    last line. Excludes any empty ranges that result from lines that are only
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   344
    present in content1. Relies on mdiff's idea of where the line endings are in
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   345
    the string.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   346
37215
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   347
    >>> from mercurial import pycompat
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   348
    >>> lines = lambda s: b'\\n'.join([c for c in pycompat.iterbytestr(s)])
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   349
    >>> difflineranges2 = lambda a, b: difflineranges(lines(a), lines(b))
37215
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   350
    >>> difflineranges2(b'', b'')
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   351
    []
37215
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   352
    >>> difflineranges2(b'a', b'')
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   353
    []
37215
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   354
    >>> difflineranges2(b'', b'A')
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   355
    [(1, 1)]
37215
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   356
    >>> difflineranges2(b'a', b'a')
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   357
    []
37215
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   358
    >>> difflineranges2(b'a', b'A')
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   359
    [(1, 1)]
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   360
    >>> difflineranges2(b'ab', b'')
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   361
    []
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   362
    >>> difflineranges2(b'', b'AB')
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   363
    [(1, 2)]
37215
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   364
    >>> difflineranges2(b'abc', b'ac')
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   365
    []
37215
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   366
    >>> difflineranges2(b'ab', b'aCb')
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   367
    [(2, 2)]
37215
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   368
    >>> difflineranges2(b'abc', b'aBc')
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   369
    [(2, 2)]
37215
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   370
    >>> difflineranges2(b'ab', b'AB')
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   371
    [(1, 2)]
37215
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   372
    >>> difflineranges2(b'abcde', b'aBcDe')
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   373
    [(2, 2), (4, 4)]
37215
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37209
diff changeset
   374
    >>> difflineranges2(b'abcde', b'aBCDe')
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   375
    [(2, 4)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   376
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   377
    ranges = []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   378
    for lines, kind in mdiff.allblocks(content1, content2):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   379
        firstline, lastline = lines[2:4]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   380
        if kind == '!' and firstline != lastline:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   381
            ranges.append((firstline + 1, lastline))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   382
    return ranges
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   383
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   384
def getbasectxs(repo, opts, revstofix):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   385
    """Returns a map of the base contexts for each revision
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   386
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   387
    The base contexts determine which lines are considered modified when we
38591
f068495a1c28 fix: add test case that shows why --whole with --base is useful
Danny Hooper <hooper@google.com>
parents: 38538
diff changeset
   388
    attempt to fix just the modified lines in a file. It also determines which
f068495a1c28 fix: add test case that shows why --whole with --base is useful
Danny Hooper <hooper@google.com>
parents: 38538
diff changeset
   389
    files we attempt to fix, so it is important to compute this even when
f068495a1c28 fix: add test case that shows why --whole with --base is useful
Danny Hooper <hooper@google.com>
parents: 38538
diff changeset
   390
    --whole is used.
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   391
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   392
    # The --base flag overrides the usual logic, and we give every revision
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   393
    # exactly the set of baserevs that the user specified.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   394
    if opts.get('base'):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   395
        baserevs = set(scmutil.revrange(repo, opts.get('base')))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   396
        if not baserevs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   397
            baserevs = {nullrev}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   398
        basectxs = {repo[rev] for rev in baserevs}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   399
        return {rev: basectxs for rev in revstofix}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   400
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   401
    # Proceed in topological order so that we can easily determine each
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   402
    # revision's baserevs by looking at its parents and their baserevs.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   403
    basectxs = collections.defaultdict(set)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   404
    for rev in sorted(revstofix):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   405
        ctx = repo[rev]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   406
        for pctx in ctx.parents():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   407
            if pctx.rev() in basectxs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   408
                basectxs[rev].update(basectxs[pctx.rev()])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   409
            else:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   410
                basectxs[rev].add(pctx)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   411
    return basectxs
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   412
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   413
def fixfile(ui, opts, fixers, fixctx, path, basectxs):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   414
    """Run any configured fixers that should affect the file in this context
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   415
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   416
    Returns the file content that results from applying the fixers in some order
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   417
    starting with the file's content in the fixctx. Fixers that support line
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   418
    ranges will affect lines that have changed relative to any of the basectxs
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   419
    (i.e. they will only avoid lines that are common to all basectxs).
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   420
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   421
    newdata = fixctx[path].data()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   422
    for fixername, fixer in fixers.iteritems():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   423
        if fixer.affects(opts, fixctx, path):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   424
            ranges = lineranges(opts, path, basectxs, fixctx, newdata)
37774
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
   425
            command = fixer.command(ui, path, ranges)
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   426
            if command is None:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   427
                continue
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   428
            ui.debug('subprocess: %s\n' % (command,))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   429
            proc = subprocess.Popen(
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   430
                command,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   431
                shell=True,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   432
                cwd='/',
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   433
                stdin=subprocess.PIPE,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   434
                stdout=subprocess.PIPE,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   435
                stderr=subprocess.PIPE)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   436
            newerdata, stderr = proc.communicate(newdata)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   437
            if stderr:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   438
                showstderr(ui, fixctx.rev(), fixername, stderr)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   439
            else:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   440
                newdata = newerdata
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   441
    return newdata
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   442
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   443
def showstderr(ui, rev, fixername, stderr):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   444
    """Writes the lines of the stderr string as warnings on the ui
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   445
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   446
    Uses the revision number and fixername to give more context to each line of
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   447
    the error message. Doesn't include file names, since those take up a lot of
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   448
    space and would tend to be included in the error message if they were
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   449
    relevant.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   450
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   451
    for line in re.split('[\r\n]+', stderr):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   452
        if line:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   453
            ui.warn(('['))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   454
            if rev is None:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   455
                ui.warn(_('wdir'), label='evolve.rev')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   456
            else:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   457
                ui.warn((str(rev)), label='evolve.rev')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   458
            ui.warn(('] %s: %s\n') % (fixername, line))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   459
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   460
def writeworkingdir(repo, ctx, filedata, replacements):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   461
    """Write new content to the working copy and check out the new p1 if any
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   462
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   463
    We check out a new revision if and only if we fixed something in both the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   464
    working directory and its parent revision. This avoids the need for a full
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   465
    update/merge, and means that the working directory simply isn't affected
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   466
    unless the --working-dir flag is given.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   467
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   468
    Directly updates the dirstate for the affected files.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   469
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   470
    for path, data in filedata.iteritems():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   471
        fctx = ctx[path]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   472
        fctx.write(data, fctx.flags())
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   473
        if repo.dirstate[path] == 'n':
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   474
            repo.dirstate.normallookup(path)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   475
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   476
    oldparentnodes = repo.dirstate.parents()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   477
    newparentnodes = [replacements.get(n, n) for n in oldparentnodes]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   478
    if newparentnodes != oldparentnodes:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   479
        repo.setparents(*newparentnodes)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   480
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   481
def replacerev(ui, repo, ctx, filedata, replacements):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   482
    """Commit a new revision like the given one, but with file content changes
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   483
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   484
    "ctx" is the original revision to be replaced by a modified one.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   485
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   486
    "filedata" is a dict that maps paths to their new file content. All other
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   487
    paths will be recreated from the original revision without changes.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   488
    "filedata" may contain paths that didn't exist in the original revision;
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   489
    they will be added.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   490
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   491
    "replacements" is a dict that maps a single node to a single node, and it is
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   492
    updated to indicate the original revision is replaced by the newly created
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   493
    one. No entry is added if the replacement's node already exists.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   494
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   495
    The new revision has the same parents as the old one, unless those parents
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   496
    have already been replaced, in which case those replacements are the parents
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   497
    of this new revision. Thus, if revisions are replaced in topological order,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   498
    there is no need to rebase them into the original topology later.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   499
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   500
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   501
    p1rev, p2rev = repo.changelog.parentrevs(ctx.rev())
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   502
    p1ctx, p2ctx = repo[p1rev], repo[p2rev]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   503
    newp1node = replacements.get(p1ctx.node(), p1ctx.node())
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   504
    newp2node = replacements.get(p2ctx.node(), p2ctx.node())
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   505
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   506
    def filectxfn(repo, memctx, path):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   507
        if path not in ctx:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   508
            return None
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   509
        fctx = ctx[path]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   510
        copied = fctx.renamed()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   511
        if copied:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   512
            copied = copied[0]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   513
        return context.memfilectx(
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   514
            repo,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   515
            memctx,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   516
            path=fctx.path(),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   517
            data=filedata.get(path, fctx.data()),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   518
            islink=fctx.islink(),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   519
            isexec=fctx.isexec(),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   520
            copied=copied)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   521
38429
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   522
    memctx = context.memctx(
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   523
        repo,
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   524
        parents=(newp1node, newp2node),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   525
        text=ctx.description(),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   526
        files=set(ctx.files()) | set(filedata.keys()),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   527
        filectxfn=filectxfn,
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   528
        user=ctx.user(),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   529
        date=ctx.date(),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   530
        extra=ctx.extra(),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   531
        branch=ctx.branch(),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   532
        editor=None)
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   533
    sucnode = memctx.commit()
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   534
    prenode = ctx.node()
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   535
    if prenode == sucnode:
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   536
        ui.debug('node %s already existed\n' % (ctx.hex()))
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   537
    else:
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38426
diff changeset
   538
        replacements[ctx.node()] = sucnode
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   539
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   540
def getfixers(ui):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   541
    """Returns a map of configured fixer tools indexed by their names
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   542
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   543
    Each value is a Fixer object with methods that implement the behavior of the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   544
    fixer's config suboptions. Does not validate the config values.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   545
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   546
    result = {}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   547
    for name in fixernames(ui):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   548
        result[name] = Fixer()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   549
        attrs = ui.configsuboptions('fix', name)[1]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   550
        for key in FIXER_ATTRS:
37618
1edf3738e000 fix: port most of the way to python 3
Augie Fackler <augie@google.com>
parents: 37595
diff changeset
   551
            setattr(result[name], pycompat.sysstr('_' + key),
1edf3738e000 fix: port most of the way to python 3
Augie Fackler <augie@google.com>
parents: 37595
diff changeset
   552
                    attrs.get(key, ''))
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   553
    return result
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   554
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   555
def fixernames(ui):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   556
    """Returns the names of [fix] config options that have suboptions"""
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   557
    names = set()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   558
    for k, v in ui.configitems('fix'):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   559
        if ':' in k:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   560
            names.add(k.split(':', 1)[0])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   561
    return names
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   562
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   563
class Fixer(object):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   564
    """Wraps the raw config values for a fixer with methods"""
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   565
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   566
    def affects(self, opts, fixctx, path):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   567
        """Should this fixer run on the file at the given path and context?"""
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   568
        return scmutil.match(fixctx, [self._fileset], opts)(path)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   569
37774
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
   570
    def command(self, ui, path, ranges):
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   571
        """A shell command to use to invoke this fixer on the given file/lines
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   572
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   573
        May return None if there is no appropriate command to run for the given
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   574
        parameters.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   575
        """
37774
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
   576
        expand = cmdutil.rendercommandtemplate
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
   577
        parts = [expand(ui, self._command,
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
   578
                        {'rootpath': path, 'basename': os.path.basename(path)})]
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   579
        if self._linerange:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   580
            if not ranges:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   581
                # No line ranges to fix, so don't run the fixer.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   582
                return None
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   583
            for first, last in ranges:
37774
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
   584
                parts.append(expand(ui, self._linerange,
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
   585
                                    {'first': first, 'last': last}))
37185
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   586
        return ' '.join(parts)