hgext/fix.py
author Martin von Zweigbergk <martinvonz@google.com>
Tue, 08 Oct 2019 15:06:18 -0700
changeset 43117 8ff1ecfadcd1
parent 43105 649d3ac37a12
child 43193 2d1f9880af1b
permissions -rw-r--r--
cleanup: join string literals that are already on one line Thanks to Kyle for noticing this and for providing the regular expression to run on the codebase. This patch has been reviewed by the test suite and they approved of it. # skip-blame: fallout from mass reformatting Differential Revision: https://phab.mercurial-scm.org/D7028
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
37183
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}
40533
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
    18
  clang-format:pattern=set:**.cpp or **.hpp
37183
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
40532
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    22
fixed file content is expected on standard output. Any output on standard error
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    23
will be displayed as a warning. If the exit status is not zero, the file will
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    24
not be affected. A placeholder warning is displayed if there is a non-zero exit
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    25
status but no standard error output. Some values may be substituted into the
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    26
command::
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    27
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    28
  {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
    29
  {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
    30
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    31
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
    32
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
    33
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
    34
substituted into the command::
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    35
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    36
  {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
    37
  {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
    38
42756
ed0da6e0d6ee fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents: 42673
diff changeset
    39
Deleted sections of a file will be ignored by :linerange, because there is no
ed0da6e0d6ee fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents: 42673
diff changeset
    40
corresponding line range in the version being fixed.
ed0da6e0d6ee fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents: 42673
diff changeset
    41
ed0da6e0d6ee fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents: 42673
diff changeset
    42
By default, tools that set :linerange will only be executed if there is at least
ed0da6e0d6ee fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents: 42673
diff changeset
    43
one changed line range. This is meant to prevent accidents like running a code
ed0da6e0d6ee fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents: 42673
diff changeset
    44
formatter in such a way that it unexpectedly reformats the whole file. If such a
ed0da6e0d6ee fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents: 42673
diff changeset
    45
tool needs to operate on unchanged files, it should set the :skipclean suboption
ed0da6e0d6ee fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents: 42673
diff changeset
    46
to false.
ed0da6e0d6ee fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents: 42673
diff changeset
    47
40533
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
    48
The :pattern suboption determines which files will be passed through each
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
    49
configured tool. See :hg:`help patterns` for possible values. If there are file
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
    50
arguments to :hg:`fix`, the intersection of these patterns is used.
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    51
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    52
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
    53
processed by :hg:`fix`::
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    54
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    55
  [fix]
40532
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    56
  maxfilesize = 2MB
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    57
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    58
Normally, execution of configured tools will continue after a failure (indicated
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    59
by a non-zero exit status). It can also be configured to abort after the first
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    60
such failure, so that no files will be affected if any tool fails. This abort
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    61
will also cause :hg:`fix` to exit with a non-zero status::
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    62
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    63
  [fix]
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
    64
  failure = abort
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
    65
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    66
When multiple tools are configured to affect a file, they execute in an order
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    67
defined by the :priority suboption. The priority suboption has a default value
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    68
of zero for each tool. Tools are executed in order of descending priority. The
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    69
execution order of tools with equal priority is unspecified. For example, you
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    70
could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    71
in a text file by ensuring that 'sort' runs before 'head'::
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    72
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    73
  [fix]
41126
d8f5c615e811 tests: use more portable flags in test-fix.t
Danny Hooper <hooper@google.com>
parents: 40570
diff changeset
    74
  sort:command = sort -n
d8f5c615e811 tests: use more portable flags in test-fix.t
Danny Hooper <hooper@google.com>
parents: 40570
diff changeset
    75
  head:command = head -n 10
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    76
  sort:pattern = numbers.txt
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    77
  head:pattern = numbers.txt
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    78
  sort:priority = 2
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    79
  head:priority = 1
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    80
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    81
To account for changes made by each tool, the line numbers used for incremental
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    82
formatting are recomputed before executing the next tool. So, each tool may see
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
    83
different values for the arguments added by the :linerange suboption.
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    84
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    85
Each fixer tool is allowed to return some metadata in addition to the fixed file
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    86
content. The metadata must be placed before the file content on stdout,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    87
separated from the file content by a zero byte. The metadata is parsed as a JSON
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    88
value (so, it should be UTF-8 encoded and contain no zero bytes). A fixer tool
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    89
is expected to produce this metadata encoding if and only if the :metadata
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    90
suboption is true::
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    91
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    92
  [fix]
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    93
  tool:command = tool --prepend-json-metadata
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    94
  tool:metadata = true
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    95
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    96
The metadata values are passed to hooks, which can be used to print summaries or
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    97
perform other post-fixing work. The supported hooks are::
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    98
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
    99
  "postfixfile"
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   100
    Run once for each file in each revision where any fixer tools made changes
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   101
    to the file content. Provides "$HG_REV" and "$HG_PATH" to identify the file,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   102
    and "$HG_METADATA" with a map of fixer names to metadata values from fixer
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   103
    tools that affected the file. Fixer tools that didn't affect the file have a
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   104
    valueof None. Only fixer tools that executed are present in the metadata.
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   105
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   106
  "postfix"
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   107
    Run once after all files and revisions have been handled. Provides
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   108
    "$HG_REPLACEMENTS" with information about what revisions were created and
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   109
    made obsolete. Provides a boolean "$HG_WDIRWRITTEN" to indicate whether any
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   110
    files in the working copy were updated. Provides a list "$HG_METADATA"
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   111
    mapping fixer tool names to lists of metadata values returned from
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   112
    executions that modified a file. This aggregates the same metadata
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   113
    previously passed to the "postfixfile" hook.
42673
74b4cd091e0d fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents: 42655
diff changeset
   114
74b4cd091e0d fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents: 42655
diff changeset
   115
Fixer tools are run the in repository's root directory. This allows them to read
74b4cd091e0d fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents: 42655
diff changeset
   116
configuration files from the working copy, or even write to the working copy.
74b4cd091e0d fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents: 42655
diff changeset
   117
The working copy is not updated to match the revision being fixed. In fact,
74b4cd091e0d fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents: 42655
diff changeset
   118
several revisions may be fixed in parallel. Writes to the working copy are not
74b4cd091e0d fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents: 42655
diff changeset
   119
amended into the revision being fixed; fixer tools should always write fixed
74b4cd091e0d fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents: 42655
diff changeset
   120
file content back to stdout as documented above.
37183
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
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   123
from __future__ import absolute_import
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   124
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   125
import collections
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   126
import itertools
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   127
import json
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   128
import os
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   129
import re
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   130
import subprocess
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   131
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   132
from mercurial.i18n import _
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   133
from mercurial.node import nullrev
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   134
from mercurial.node import wdirrev
43087
66f2cc210a29 py3: manually import pycompat.setattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43077
diff changeset
   135
from mercurial.pycompat import setattr
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   136
39826
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 38967
diff changeset
   137
from mercurial.utils import (
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 38967
diff changeset
   138
    procutil,
42756
ed0da6e0d6ee fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents: 42673
diff changeset
   139
    stringutil,
39826
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 38967
diff changeset
   140
)
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 38967
diff changeset
   141
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   142
from mercurial import (
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   143
    cmdutil,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   144
    context,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   145
    copies,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   146
    error,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   147
    mdiff,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   148
    merge,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   149
    obsolete,
37618
1edf3738e000 fix: port most of the way to python 3
Augie Fackler <augie@google.com>
parents: 37595
diff changeset
   150
    pycompat,
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   151
    registrar,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   152
    scmutil,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   153
    util,
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   154
    worker,
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   155
)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   156
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   157
# 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
   158
# 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
   159
# 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
   160
# leave the attribute unspecified.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   161
testedwith = b'ships-with-hg-core'
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   162
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   163
cmdtable = {}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   164
command = registrar.command(cmdtable)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   165
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   166
configtable = {}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   167
configitem = registrar.configitem(configtable)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   168
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   169
# Register the suboptions allowed for each configured fixer, and default values.
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
   170
FIXER_ATTRS = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   171
    b'command': None,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   172
    b'linerange': None,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   173
    b'pattern': None,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   174
    b'priority': 0,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   175
    b'metadata': b'false',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   176
    b'skipclean': b'true',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   177
    b'enabled': b'true',
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
   178
}
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   179
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
   180
for key, default in FIXER_ATTRS.items():
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   181
    configitem(b'fix', b'.*(:%s)?' % key, default=default, generic=True)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   182
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   183
# 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
   184
# 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
   185
# user.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   186
configitem(b'fix', b'maxfilesize', default=b'2MB')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   187
40532
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
   188
# Allow fix commands to exit non-zero if an executed fixer tool exits non-zero.
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
   189
# This helps users do shell scripts that stop when a fixer tool signals a
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
   190
# problem.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   191
configitem(b'fix', b'failure', default=b'continue')
40532
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
   192
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   193
40532
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
   194
def checktoolfailureaction(ui, message, hint=None):
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
   195
    """Abort with 'message' if fix.failure=abort"""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   196
    action = ui.config(b'fix', b'failure')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   197
    if action not in (b'continue', b'abort'):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   198
        raise error.Abort(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   199
            _(b'unknown fix.failure action: %s') % (action,),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   200
            hint=_(b'use "continue" or "abort"'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   201
        )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   202
    if action == b'abort':
40532
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
   203
        raise error.Abort(message, hint=hint)
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
   204
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   205
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   206
allopt = (b'', b'all', False, _(b'fix all non-public non-obsolete revisions'))
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   207
baseopt = (
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   208
    b'',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   209
    b'base',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   210
    [],
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   211
    _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   212
        b'revisions to diff against (overrides automatic '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   213
        b'selection, and applies to every revision being '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   214
        b'fixed)'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   215
    ),
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   216
    _(b'REV'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   217
)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   218
revopt = (b'r', b'rev', [], _(b'revisions to fix'), _(b'REV'))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   219
wdiropt = (b'w', b'working-dir', False, _(b'fix the working directory'))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   220
wholeopt = (b'', b'whole', False, _(b'always fix every line of a file'))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   221
usage = _(b'[OPTION]... [FILE]...')
38949
b0c591950e51 fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents: 38860
diff changeset
   222
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   223
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   224
@command(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   225
    b'fix',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   226
    [allopt, baseopt, revopt, wdiropt, wholeopt],
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   227
    usage,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   228
    helpcategory=command.CATEGORY_FILE_CONTENTS,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   229
)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   230
def fix(ui, repo, *pats, **opts):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   231
    """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
   232
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   233
    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
   234
    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
   235
    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
   236
    whole file regardless of --whole.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   237
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   238
    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
   239
    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
   240
    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
   241
    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
   242
    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
   243
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   244
    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
   245
    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
   246
    directory will update to the replacement revision.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   247
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   248
    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
   249
    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
   250
    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
   251
    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
   252
    """
37618
1edf3738e000 fix: port most of the way to python 3
Augie Fackler <augie@google.com>
parents: 37595
diff changeset
   253
    opts = pycompat.byteskwargs(opts)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   254
    if opts[b'all']:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   255
        if opts[b'rev']:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   256
            raise error.Abort(_(b'cannot specify both "--rev" and "--all"'))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   257
        opts[b'rev'] = [b'not public() and not obsolete()']
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   258
        opts[b'working_dir'] = True
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   259
    with repo.wlock(), repo.lock(), repo.transaction(b'fix'):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   260
        revstofix = getrevstofix(ui, repo, opts)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   261
        basectxs = getbasectxs(repo, opts, revstofix)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   262
        workqueue, numitems = getworkqueue(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   263
            ui, repo, pats, opts, revstofix, basectxs
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   264
        )
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   265
        fixers = getfixers(ui)
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   266
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   267
        # 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: 38423
diff changeset
   268
        # revision, so we can use all available parallelism.
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   269
        def getfixes(items):
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   270
            for rev, path in items:
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   271
                ctx = repo[rev]
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   272
                olddata = ctx[path].data()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   273
                metadata, newdata = fixfile(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   274
                    ui, repo, opts, fixers, ctx, path, basectxs[rev]
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   275
                )
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   276
                # 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: 38423
diff changeset
   277
                # produce one result per item either way.
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   278
                yield (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   279
                    rev,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   280
                    path,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   281
                    metadata,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   282
                    newdata if newdata != olddata else None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   283
                )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   284
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   285
        results = worker.worker(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   286
            ui, 1.0, getfixes, tuple(), workqueue, threadsafe=False
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   287
        )
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   288
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   289
        # 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: 38423
diff changeset
   290
        # 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: 38423
diff changeset
   291
        # 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: 38423
diff changeset
   292
        # 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: 38423
diff changeset
   293
        # 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: 38423
diff changeset
   294
        # it makes the results more easily reproducible.
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   295
        filedata = collections.defaultdict(dict)
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   296
        aggregatemetadata = collections.defaultdict(list)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   297
        replacements = {}
38950
35bc4b6e132d fix: correctly set wdirwritten given that the dict item is deleted
Danny Hooper <hooper@google.com>
parents: 38949
diff changeset
   298
        wdirwritten = False
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   299
        commitorder = sorted(revstofix, reverse=True)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   300
        with ui.makeprogress(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   301
            topic=_(b'fixing'), unit=_(b'files'), total=sum(numitems.values())
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   302
        ) as progress:
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   303
            for rev, path, filerevmetadata, newdata in results:
38537
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   304
                progress.increment(item=path)
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   305
                for fixername, fixermetadata in filerevmetadata.items():
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   306
                    aggregatemetadata[fixername].append(fixermetadata)
38537
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   307
                if newdata is not None:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   308
                    filedata[rev][path] = newdata
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   309
                    hookargs = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   310
                        b'rev': rev,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   311
                        b'path': path,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   312
                        b'metadata': filerevmetadata,
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   313
                    }
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   314
                    repo.hook(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   315
                        b'postfixfile',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   316
                        throw=False,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   317
                        **pycompat.strkwargs(hookargs)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   318
                    )
38537
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   319
                numitems[rev] -= 1
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   320
                # 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: 38536
diff changeset
   321
                # 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: 38536
diff changeset
   322
                # 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: 38536
diff changeset
   323
                # be ready out of order.
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   324
                while commitorder and not numitems[commitorder[-1]]:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   325
                    rev = commitorder.pop()
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   326
                    ctx = repo[rev]
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   327
                    if rev == wdirrev:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   328
                        writeworkingdir(repo, ctx, filedata[rev], replacements)
38950
35bc4b6e132d fix: correctly set wdirwritten given that the dict item is deleted
Danny Hooper <hooper@google.com>
parents: 38949
diff changeset
   329
                        wdirwritten = bool(filedata[rev])
38537
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   330
                    else:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   331
                        replacerev(ui, repo, ctx, filedata[rev], replacements)
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
   332
                    del filedata[rev]
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   333
38950
35bc4b6e132d fix: correctly set wdirwritten given that the dict item is deleted
Danny Hooper <hooper@google.com>
parents: 38949
diff changeset
   334
        cleanup(repo, replacements, wdirwritten)
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   335
        hookargs = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   336
            b'replacements': replacements,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   337
            b'wdirwritten': wdirwritten,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   338
            b'metadata': aggregatemetadata,
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   339
        }
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   340
        repo.hook(b'postfix', throw=True, **pycompat.strkwargs(hookargs))
38811
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   341
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   342
38811
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   343
def cleanup(repo, replacements, wdirwritten):
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   344
    """Calls scmutil.cleanupnodes() with the given replacements.
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   345
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   346
    "replacements" is a dict from nodeid to nodeid, with one key and one value
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   347
    for every revision that was affected by fixing. This is slightly different
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   348
    from cleanupnodes().
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   349
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   350
    "wdirwritten" is a bool which tells whether the working copy was affected by
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   351
    fixing, since it has no entry in "replacements".
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   352
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   353
    Useful as a hook point for extending "hg fix" with output summarizing the
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   354
    effects of the command, though we choose not to output anything here.
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
   355
    """
43105
649d3ac37a12 py3: define and use pycompat.iteritems() for hgext/
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43087
diff changeset
   356
    replacements = {
649d3ac37a12 py3: define and use pycompat.iteritems() for hgext/
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43087
diff changeset
   357
        prec: [succ] for prec, succ in pycompat.iteritems(replacements)
649d3ac37a12 py3: define and use pycompat.iteritems() for hgext/
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43087
diff changeset
   358
    }
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   359
    scmutil.cleanupnodes(repo, replacements, b'fix', fixphase=True)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   360
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   361
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   362
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
   363
    """"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
   364
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   365
    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
   366
    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
   367
    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
   368
    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
   369
    or into a replacement revision.
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   370
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   371
    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: 38423
diff changeset
   372
    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: 38423
diff changeset
   373
    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: 38423
diff changeset
   374
    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: 38423
diff changeset
   375
    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: 38423
diff changeset
   376
    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: 38423
diff changeset
   377
    the fixes later.
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   378
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   379
    workqueue = []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   380
    numitems = collections.defaultdict(int)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   381
    maxfilesize = ui.configbytes(b'fix', b'maxfilesize')
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
   382
    for rev in sorted(revstofix):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   383
        fixctx = repo[rev]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   384
        match = scmutil.match(fixctx, pats, opts)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   385
        for path in sorted(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   386
            pathstofix(ui, repo, pats, opts, match, basectxs[rev], fixctx)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   387
        ):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   388
            fctx = fixctx[path]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   389
            if fctx.islink():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   390
                continue
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   391
            if fctx.size() > maxfilesize:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   392
                ui.warn(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   393
                    _(b'ignoring file larger than %s: %s\n')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   394
                    % (util.bytecount(maxfilesize), path)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   395
                )
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   396
                continue
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   397
            workqueue.append((rev, path))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   398
            numitems[rev] += 1
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   399
    return workqueue, numitems
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   400
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   401
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   402
def getrevstofix(ui, repo, opts):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   403
    """Returns the set of revision numbers that should be fixed"""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   404
    revs = set(scmutil.revrange(repo, opts[b'rev']))
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   405
    for rev in revs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   406
        checkfixablectx(ui, repo, repo[rev])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   407
    if revs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   408
        cmdutil.checkunfinished(repo)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   409
        checknodescendants(repo, revs)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   410
    if opts.get(b'working_dir'):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   411
        revs.add(wdirrev)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   412
        if list(merge.mergestate.read(repo).unresolved()):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   413
            raise error.Abort(b'unresolved conflicts', hint=b"use 'hg resolve'")
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   414
    if not revs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   415
        raise error.Abort(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   416
            b'no changesets specified', hint=b'use --rev or --working-dir'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   417
        )
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   418
    return revs
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   419
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   420
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   421
def checknodescendants(repo, revs):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   422
    if not obsolete.isenabled(repo, obsolete.allowunstableopt) and repo.revs(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   423
        b'(%ld::) - (%ld)', revs, revs
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   424
    ):
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   425
        raise error.Abort(
43117
8ff1ecfadcd1 cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents: 43105
diff changeset
   426
            _(b'can only fix a changeset together with all its descendants')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   427
        )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   428
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   429
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   430
def checkfixablectx(ui, repo, ctx):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   431
    """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
   432
    if not ctx.mutable():
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   433
        raise error.Abort(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   434
            b'can\'t fix immutable changeset %s'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   435
            % (scmutil.formatchangeid(ctx),)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   436
        )
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   437
    if ctx.obsolete():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   438
        # It would be better to actually check if the revision has a successor.
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   439
        allowdivergence = ui.configbool(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   440
            b'experimental', b'evolution.allowdivergence'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   441
        )
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   442
        if not allowdivergence:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   443
            raise error.Abort(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   444
                b'fixing obsolete revision could cause divergence'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   445
            )
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   446
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   447
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   448
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
   449
    """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
   450
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   451
    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
   452
    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
   453
    ancestors of the context being fixed.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   454
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   455
    files = set()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   456
    for basectx in basectxs:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   457
        stat = basectx.status(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   458
            fixctx, match=match, listclean=bool(pats), listunknown=bool(pats)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   459
        )
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   460
        files.update(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   461
            set(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   462
                itertools.chain(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   463
                    stat.added, stat.modified, stat.clean, stat.unknown
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   464
                )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   465
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   466
        )
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   467
    return files
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   468
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   469
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   470
def lineranges(opts, path, basectxs, fixctx, content2):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   471
    """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
   472
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   473
    Of the form [(10, 20), (30, 40)].
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   474
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   475
    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
   476
    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
   477
    renamed versus any of them.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   478
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   479
    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
   480
    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
   481
    """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   482
    if opts.get(b'whole'):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   483
        # 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
   484
        # idea of how many lines are in the file, instead of reimplementing it.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   485
        return difflineranges(b'', content2)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   486
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   487
    rangeslist = []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   488
    for basectx in basectxs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   489
        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
   490
        if basepath in basectx:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   491
            content1 = basectx[basepath].data()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   492
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   493
            content1 = b''
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   494
        rangeslist.extend(difflineranges(content1, content2))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   495
    return unionranges(rangeslist)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   496
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   497
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   498
def unionranges(rangeslist):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   499
    """Return the union of some closed intervals
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
    >>> unionranges([])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   502
    []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   503
    >>> unionranges([(1, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   504
    [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   505
    >>> unionranges([(1, 100), (1, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   506
    [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   507
    >>> unionranges([(1, 100), (2, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   508
    [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   509
    >>> unionranges([(1, 99), (1, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   510
    [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   511
    >>> unionranges([(1, 100), (40, 60)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   512
    [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   513
    >>> unionranges([(1, 49), (50, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   514
    [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   515
    >>> unionranges([(1, 48), (50, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   516
    [(1, 48), (50, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   517
    >>> unionranges([(1, 2), (3, 4), (5, 6)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   518
    [(1, 6)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   519
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   520
    rangeslist = sorted(set(rangeslist))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   521
    unioned = []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   522
    if rangeslist:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   523
        unioned, rangeslist = [rangeslist[0]], rangeslist[1:]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   524
    for a, b in rangeslist:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   525
        c, d = unioned[-1]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   526
        if a > d + 1:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   527
            unioned.append((a, b))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   528
        else:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   529
            unioned[-1] = (c, max(b, d))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   530
    return unioned
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   531
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   532
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   533
def difflineranges(content1, content2):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   534
    """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
   535
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   536
    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
   537
    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
   538
    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
   539
    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
   540
    the string.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   541
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   542
    >>> from mercurial import pycompat
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   543
    >>> lines = lambda s: b'\\n'.join([c for c in pycompat.iterbytestr(s)])
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   544
    >>> difflineranges2 = lambda a, b: difflineranges(lines(a), lines(b))
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   545
    >>> difflineranges2(b'', b'')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   546
    []
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   547
    >>> difflineranges2(b'a', b'')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   548
    []
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   549
    >>> difflineranges2(b'', b'A')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   550
    [(1, 1)]
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   551
    >>> difflineranges2(b'a', b'a')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   552
    []
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   553
    >>> difflineranges2(b'a', b'A')
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   554
    [(1, 1)]
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   555
    >>> difflineranges2(b'ab', b'')
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   556
    []
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   557
    >>> difflineranges2(b'', b'AB')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   558
    [(1, 2)]
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   559
    >>> difflineranges2(b'abc', b'ac')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   560
    []
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   561
    >>> difflineranges2(b'ab', b'aCb')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   562
    [(2, 2)]
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   563
    >>> difflineranges2(b'abc', b'aBc')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   564
    [(2, 2)]
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   565
    >>> difflineranges2(b'ab', b'AB')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   566
    [(1, 2)]
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   567
    >>> difflineranges2(b'abcde', b'aBcDe')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   568
    [(2, 2), (4, 4)]
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
   569
    >>> difflineranges2(b'abcde', b'aBCDe')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   570
    [(2, 4)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   571
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   572
    ranges = []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   573
    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
   574
        firstline, lastline = lines[2:4]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   575
        if kind == b'!' and firstline != lastline:
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   576
            ranges.append((firstline + 1, lastline))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   577
    return ranges
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   578
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   579
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   580
def getbasectxs(repo, opts, revstofix):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   581
    """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
   582
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   583
    The base contexts determine which lines are considered modified when we
38590
f068495a1c28 fix: add test case that shows why --whole with --base is useful
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
   584
    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: 38537
diff changeset
   585
    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: 38537
diff changeset
   586
    --whole is used.
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   587
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   588
    # 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
   589
    # exactly the set of baserevs that the user specified.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   590
    if opts.get(b'base'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   591
        baserevs = set(scmutil.revrange(repo, opts.get(b'base')))
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   592
        if not baserevs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   593
            baserevs = {nullrev}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   594
        basectxs = {repo[rev] for rev in baserevs}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   595
        return {rev: basectxs for rev in revstofix}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   596
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   597
    # 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
   598
    # 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
   599
    basectxs = collections.defaultdict(set)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   600
    for rev in sorted(revstofix):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   601
        ctx = repo[rev]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   602
        for pctx in ctx.parents():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   603
            if pctx.rev() in basectxs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   604
                basectxs[rev].update(basectxs[pctx.rev()])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   605
            else:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   606
                basectxs[rev].add(pctx)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   607
    return basectxs
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   608
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   609
42673
74b4cd091e0d fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents: 42655
diff changeset
   610
def fixfile(ui, repo, opts, fixers, fixctx, path, basectxs):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   611
    """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
   612
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   613
    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
   614
    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
   615
    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
   616
    (i.e. they will only avoid lines that are common to all basectxs).
38967
a009589cd32a fix: determine fixer tool failure by exit code instead of stderr
Danny Hooper <hooper@google.com>
parents: 38950
diff changeset
   617
a009589cd32a fix: determine fixer tool failure by exit code instead of stderr
Danny Hooper <hooper@google.com>
parents: 38950
diff changeset
   618
    A fixer tool's stdout will become the file's new content if and only if it
42673
74b4cd091e0d fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents: 42655
diff changeset
   619
    exits with code zero. The fixer tool's working directory is the repository's
74b4cd091e0d fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents: 42655
diff changeset
   620
    root.
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   621
    """
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   622
    metadata = {}
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   623
    newdata = fixctx[path].data()
43105
649d3ac37a12 py3: define and use pycompat.iteritems() for hgext/
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43087
diff changeset
   624
    for fixername, fixer in pycompat.iteritems(fixers):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   625
        if fixer.affects(opts, fixctx, path):
42758
e9f503074044 fix: pass line ranges as value instead of callback
Danny Hooper <hooper@google.com>
parents: 42757
diff changeset
   626
            ranges = lineranges(opts, path, basectxs, fixctx, newdata)
e9f503074044 fix: pass line ranges as value instead of callback
Danny Hooper <hooper@google.com>
parents: 42757
diff changeset
   627
            command = fixer.command(ui, path, ranges)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   628
            if command is None:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   629
                continue
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   630
            ui.debug(b'subprocess: %s\n' % (command,))
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   631
            proc = subprocess.Popen(
39836
f1d6021453c2 py3: remove a couple of superfluous calls to pycompat.rapply()
Matt Harbison <matt_harbison@yahoo.com>
parents: 39826
diff changeset
   632
                procutil.tonativestr(command),
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   633
                shell=True,
42673
74b4cd091e0d fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents: 42655
diff changeset
   634
                cwd=repo.root,
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   635
                stdin=subprocess.PIPE,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   636
                stdout=subprocess.PIPE,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   637
                stderr=subprocess.PIPE,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   638
            )
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   639
            stdout, stderr = proc.communicate(newdata)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   640
            if stderr:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   641
                showstderr(ui, fixctx.rev(), fixername, stderr)
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   642
            newerdata = stdout
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   643
            if fixer.shouldoutputmetadata():
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   644
                try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   645
                    metadatajson, newerdata = stdout.split(b'\0', 1)
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   646
                    metadata[fixername] = json.loads(metadatajson)
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   647
                except ValueError:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   648
                    ui.warn(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   649
                        _(b'ignored invalid output from fixer tool: %s\n')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   650
                        % (fixername,)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   651
                    )
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   652
                    continue
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   653
            else:
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   654
                metadata[fixername] = None
38967
a009589cd32a fix: determine fixer tool failure by exit code instead of stderr
Danny Hooper <hooper@google.com>
parents: 38950
diff changeset
   655
            if proc.returncode == 0:
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   656
                newdata = newerdata
40532
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
   657
            else:
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
   658
                if not stderr:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   659
                    message = _(b'exited with status %d\n') % (proc.returncode,)
40532
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
   660
                    showstderr(ui, fixctx.rev(), fixername, message)
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
   661
                checktoolfailureaction(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   662
                    ui,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   663
                    _(b'no fixes will be applied'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   664
                    hint=_(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   665
                        b'use --config fix.failure=continue to apply any '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   666
                        b'successful fixes anyway'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   667
                    ),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   668
                )
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   669
    return metadata, newdata
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   670
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   671
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   672
def showstderr(ui, rev, fixername, stderr):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   673
    """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
   674
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   675
    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
   676
    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
   677
    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
   678
    relevant.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   679
    """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   680
    for line in re.split(b'[\r\n]+', stderr):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   681
        if line:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   682
            ui.warn(b'[')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   683
            if rev is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   684
                ui.warn(_(b'wdir'), label=b'evolve.rev')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   685
            else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   686
                ui.warn((str(rev)), label=b'evolve.rev')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   687
            ui.warn(b'] %s: %s\n' % (fixername, line))
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   688
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   689
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   690
def writeworkingdir(repo, ctx, filedata, replacements):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   691
    """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
   692
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   693
    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
   694
    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
   695
    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
   696
    unless the --working-dir flag is given.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   697
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   698
    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
   699
    """
43105
649d3ac37a12 py3: define and use pycompat.iteritems() for hgext/
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43087
diff changeset
   700
    for path, data in pycompat.iteritems(filedata):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   701
        fctx = ctx[path]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   702
        fctx.write(data, fctx.flags())
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   703
        if repo.dirstate[path] == b'n':
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   704
            repo.dirstate.normallookup(path)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   705
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   706
    oldparentnodes = repo.dirstate.parents()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   707
    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
   708
    if newparentnodes != oldparentnodes:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   709
        repo.setparents(*newparentnodes)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   710
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   711
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   712
def replacerev(ui, repo, ctx, filedata, replacements):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   713
    """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
   714
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   715
    "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
   716
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   717
    "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
   718
    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
   719
    "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
   720
    they will be added.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   721
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   722
    "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
   723
    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
   724
    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
   725
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   726
    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
   727
    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
   728
    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
   729
    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
   730
    """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   731
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   732
    p1rev, p2rev = repo.changelog.parentrevs(ctx.rev())
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   733
    p1ctx, p2ctx = repo[p1rev], repo[p2rev]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   734
    newp1node = replacements.get(p1ctx.node(), p1ctx.node())
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   735
    newp2node = replacements.get(p2ctx.node(), p2ctx.node())
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   736
40570
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
   737
    # We don't want to create a revision that has no changes from the original,
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
   738
    # but we should if the original revision's parent has been replaced.
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
   739
    # Otherwise, we would produce an orphan that needs no actual human
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
   740
    # intervention to evolve. We can't rely on commit() to avoid creating the
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
   741
    # un-needed revision because the extra field added below produces a new hash
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
   742
    # regardless of file content changes.
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   743
    if (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   744
        not filedata
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   745
        and p1ctx.node() not in replacements
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   746
        and p2ctx.node() not in replacements
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   747
    ):
40570
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
   748
        return
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
   749
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   750
    def filectxfn(repo, memctx, path):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   751
        if path not in ctx:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   752
            return None
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   753
        fctx = ctx[path]
41994
550a172a603b memctx: rename constructor argument "copied" to "copysource" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41777
diff changeset
   754
        copysource = fctx.copysource()
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   755
        return context.memfilectx(
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   756
            repo,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   757
            memctx,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   758
            path=fctx.path(),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   759
            data=filedata.get(path, fctx.data()),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   760
            islink=fctx.islink(),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   761
            isexec=fctx.isexec(),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   762
            copysource=copysource,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   763
        )
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   764
40570
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
   765
    extra = ctx.extra().copy()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   766
    extra[b'fix_source'] = ctx.hex()
40570
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
   767
38423
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   768
    memctx = context.memctx(
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   769
        repo,
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   770
        parents=(newp1node, newp2node),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   771
        text=ctx.description(),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   772
        files=set(ctx.files()) | set(filedata.keys()),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   773
        filectxfn=filectxfn,
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   774
        user=ctx.user(),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   775
        date=ctx.date(),
40570
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
   776
        extra=extra,
38423
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   777
        branch=ctx.branch(),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   778
        editor=None,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   779
    )
38423
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   780
    sucnode = memctx.commit()
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   781
    prenode = ctx.node()
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   782
    if prenode == sucnode:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   783
        ui.debug(b'node %s already existed\n' % (ctx.hex()))
38423
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   784
    else:
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
   785
        replacements[ctx.node()] = sucnode
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   786
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   787
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   788
def getfixers(ui):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   789
    """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
   790
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   791
    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
   792
    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
   793
    """
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
   794
    fixers = {}
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   795
    for name in fixernames(ui):
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
   796
        fixers[name] = Fixer()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   797
        attrs = ui.configsuboptions(b'fix', name)[1]
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
   798
        for key, default in FIXER_ATTRS.items():
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   799
            setattr(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   800
                fixers[name],
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   801
                pycompat.sysstr(b'_' + key),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   802
                attrs.get(key, default),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   803
            )
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
   804
        fixers[name]._priority = int(fixers[name]._priority)
42757
2d70b1118af2 fix: correctly parse the :metadata subconfig
Danny Hooper <hooper@google.com>
parents: 42756
diff changeset
   805
        fixers[name]._metadata = stringutil.parsebool(fixers[name]._metadata)
42756
ed0da6e0d6ee fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents: 42673
diff changeset
   806
        fixers[name]._skipclean = stringutil.parsebool(fixers[name]._skipclean)
43058
808a57a08470 fix: add :enabled sub-config for fixer tools
Danny Hooper <hooper@google.com>
parents: 42758
diff changeset
   807
        fixers[name]._enabled = stringutil.parsebool(fixers[name]._enabled)
42655
2987d015aba4 fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents: 42653
diff changeset
   808
        # Don't use a fixer if it has no pattern configured. It would be
2987d015aba4 fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents: 42653
diff changeset
   809
        # dangerous to let it affect all files. It would be pointless to let it
2987d015aba4 fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents: 42653
diff changeset
   810
        # affect no files. There is no reasonable subset of files to use as the
2987d015aba4 fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents: 42653
diff changeset
   811
        # default.
2987d015aba4 fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents: 42653
diff changeset
   812
        if fixers[name]._pattern is None:
2987d015aba4 fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents: 42653
diff changeset
   813
            ui.warn(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   814
                _(b'fixer tool has no pattern configuration: %s\n') % (name,)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   815
            )
42655
2987d015aba4 fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents: 42653
diff changeset
   816
            del fixers[name]
43058
808a57a08470 fix: add :enabled sub-config for fixer tools
Danny Hooper <hooper@google.com>
parents: 42758
diff changeset
   817
        elif not fixers[name]._enabled:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   818
            ui.debug(b'ignoring disabled fixer tool: %s\n' % (name,))
43058
808a57a08470 fix: add :enabled sub-config for fixer tools
Danny Hooper <hooper@google.com>
parents: 42758
diff changeset
   819
            del fixers[name]
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
   820
    return collections.OrderedDict(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   821
        sorted(fixers.items(), key=lambda item: item[1]._priority, reverse=True)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   822
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   823
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   824
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   825
def fixernames(ui):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   826
    """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
   827
    names = set()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   828
    for k, v in ui.configitems(b'fix'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   829
        if b':' in k:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   830
            names.add(k.split(b':', 1)[0])
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   831
    return names
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   832
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   833
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   834
class Fixer(object):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   835
    """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
   836
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   837
    def affects(self, opts, fixctx, path):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   838
        """Should this fixer run on the file at the given path and context?"""
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   839
        return self._pattern is not None and scmutil.match(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   840
            fixctx, [self._pattern], opts
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   841
        )(path)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   842
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   843
    def shouldoutputmetadata(self):
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   844
        """Should the stdout of this fixer start with JSON and a null byte?"""
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   845
        return self._metadata
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
   846
42758
e9f503074044 fix: pass line ranges as value instead of callback
Danny Hooper <hooper@google.com>
parents: 42757
diff changeset
   847
    def command(self, ui, path, ranges):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   848
        """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
   849
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   850
        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
   851
        parameters.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   852
        """
37774
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
   853
        expand = cmdutil.rendercommandtemplate
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   854
        parts = [
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   855
            expand(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   856
                ui,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   857
                self._command,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   858
                {b'rootpath': path, b'basename': os.path.basename(path)},
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   859
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   860
        ]
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   861
        if self._linerange:
42756
ed0da6e0d6ee fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents: 42673
diff changeset
   862
            if self._skipclean and not ranges:
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   863
                # 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
   864
                return None
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
   865
            for first, last in ranges:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   866
                parts.append(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   867
                    expand(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   868
                        ui, self._linerange, {b'first': first, b'last': last}
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   869
                    )
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43058
diff changeset
   870
                )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   871
        return b' '.join(parts)